Типы повторного использования в текущей сборке для прокси WCF
VS WCF-интеграция имеет приятный вариант "Типы повторного использования в проверенных сборках". Проблема в том, что мне нужно то же самое, но для текущей сборки. Некоторые из типов уже определены в моей сборке, и мне нужно их повторно использовать.
Сценарий использования:
- У меня есть сборка, и здесь есть TypeA.
- Я добавляю Service Reference, и один из методов возвращает тип, полностью совместимый с TypeA (свойства, имя).
- Добавить Service Reference генерирует прокси-сервер, но он воссоздает новый TypeA внутри.
На шаге 3 мне нужен прокси-сервер, который вернет TypeA. Не новый TypeA.
Ответы
Ответ 1
Если я понимаю, что вы хотите сделать, то это сценарий, с которым я обычно сталкиваюсь, и хорошо, WCF имеет достойный ответ: просто не используйте SvcUtil/WS Service Reference wizards.
Если у вас есть большинство классов контрактов, уже определенных на вашей стороне клиента (будь то, потому что у вас есть общая сборка или у вас есть эквивалентные классы, определенные в вашем проекте), вы можете просто перейти к следующему шагу и либо импортировать полный контракт на обслуживание в виде кода или просто переопределить его на стороне клиента.
Нет ничего, что заставило бы вас использовать svcutil и друзей, просто определите свой интерфейс и либо напрямую используйте модель канала (например, ChannelFactory <T> и друзья), либо, если вы предпочитаете использовать прокси-классы, просто создайте свой собственный ClientBase <T> -пределенный класс. Это действительно очень легко, и это сэкономит вам неприятности в долгосрочной перспективе.
Ответ 2
Существует простой способ совместного использования типов между клиентом и сервисом, просто добавив ссылку на сборку общего типа к вашему клиенту ПЕРЕД добавлением служебной ссылки.
Здесь вы можете найти подробный сценарий и образец проекта:
http://blog.walteralmeida.com/2010/08/wcf-tips-and-tricks-share-types-between-server-and-client.html
Ответ 3
У меня была такая же проблема, и я хотел, чтобы тестовая проводка указывала на пару сервисов. Каждая служба будет иметь общие данные.
Что нужно сделать:
- Используйте svcutil с /t: метаданные на каждом URL-адресе.
- Переименуйте все сгенерированные файлы с чем-то уникальным для службы (например, переименуйте lala.xsd в 1_lala.xsd)
- Скопировать все сгенерированные файлы в одно место
- Используйте svcutil с *.xsd.wsdl/out:output.cs/namespace:, MySpecialNamespace, чтобы сгенерировать ВСЕ контракты на обслуживание и datacontracts в один файл.
Если вы хотите быть хитрым: используйте следующий шаблон T4:
<#@ template language="C#v4.0" hostspecific="True"#>
<#@ import namespace="System.Diagnostics" #>
<#@ import namespace="System.IO" #>
<#=GetGeneratedCode(
"http://localhost/Service/Service1.svc",
"http://localhost/Service/Service2.svc",
"http://localhost/Service/Service3.svc",
"http://localhost/Service/Service4.svc"
)#>
<#+
const string _svcutil = @"C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin\svcutil.exe";
private string GetGeneratedCode(params string[] urls)
{
var tmp = GetTemporaryDirectory();
foreach (var url in urls)
{
GetMetadata(url, tmp);
}
RunSvcutil(tmp, "*.wsdl *.xsd /out:output.cs /namespace:*," + Path.GetFileNameWithoutExtension(Host.TemplateFile));
var result = File.ReadAllText(Path.Combine(tmp, "output.cs"));
return result;
}
private static void RunSvcutil(string workingFolder, string arguments)
{
var processInfo = new ProcessStartInfo(_svcutil);
processInfo.Arguments = arguments;
processInfo.WorkingDirectory = workingFolder;
var p = Process.Start(processInfo);
p.WaitForExit();
}
private static void GetMetadata(string url, string destination)
{
var workingFolder = GetTemporaryDirectory();
RunSvcutil(workingFolder, string.Format("/t:metadata \"{0}\"", url));
foreach (var filename in Directory.GetFiles(workingFolder))
{
File.Copy(filename, Path.Combine(destination, Path.GetFileNameWithoutExtension(url) + "_" + Path.GetFileName(filename)));
}
}
private static string GetTemporaryDirectory()
{
string tempDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
Directory.CreateDirectory(tempDirectory);
return tempDirectory;
}
#>