Совместимость веб-сервисов и интерфейсов
-
20-08-2019 - |
Вопрос
Добавление ссылки на службу к веб-службе (это все WCF) в Visual Studio приводит к созданию некоторого сгенерированного кода, включая повторное описание предоставляемого интерфейса на стороне клиента.
Я понимаю, почему создается этот интерфейс:возможно, вы используете сторонний сервис и не имеете доступа к реальному интерфейсу.
Но я делаю, и эти двое не назначение совместимо, даже несмотря на то, что прозрачный прокси-сервер действительно точно реализует интерфейс, к которому я хочу применить.
Я могу использовать отражение, но это некрасиво.Есть ли какой-нибудь способ преодолеть эту искусственную безопасность типов и ввести метаданные, чтобы я мог использовать интерфейс с классом?
Моя конкретная проблема отличается от нормы сложными способами, которые связаны с одним клиентом, который использует некоторые производные базового класса напрямую и использует другие удаленно через ссылки на службы.Базовый класс для каждого сервера должен хранить ссылки на подписавшихся клиентов в коллекции для перечисления, чтобы уведомлять о событиях, и проблема заключалась в изменении типа из-за использования прокси.
Ни один из этих ответов не решает мою конкретную проблему, но каждый отдельный ответ был поучительным и полезным.Я нашел свое собственное решение (использовать двойную привязку), но я бы никогда не додумался до этого, если бы вы радикально не улучшили мое понимание всего бизнеса.
Три отличных ответа.Как выбрать только один?Я выбираю первое, потому что это напрямую решает проблему, которую я сначала мысль У меня было.
Решение
Когда вы добавите ссылку на службу, перейдите в раздел "Дополнительно" и убедитесь, что выбран параметр "Повторно использовать типы в ссылочных сборках" и что выбрана сборка, содержащая ваше определение интерфейса.Вы также можете сделать это с помощью существующей ссылки на службу, щелкнув по ней правой кнопкой мыши и перейдя в раздел "Настроить".
Другие советы
Если у вас уже есть contract dll на клиенте, вам даже не нужна ссылка на службу (если только вы не используете ее для написания кода настройки для себя) - вы можете просто создать подкласс ClientBase и предоставить Канал и использовать это напрямую - что-то вроде (без IDE под рукой ...):
public class WcfClient<T> : ClientBase<T> where T : class
{
public new T Channel {get {return base.Channel;}}
}
Тогда вы можете просто делать такие вещи, как:
using(var client = new WcfClient<IFoo>())
{
client.Channel.Bar(); // defined by IFoo
}
Вам все еще нужны параметры конфигурации в конфигурации, чтобы определить адрес, привязку и т.д. - Но это менее запутанно, чем генерация прокси.Кроме того, вы можете выбрать повторную реализацию IDipsoable
чтобы справиться с тем фактом, что прокси WCF могут выбрасывать в Dispose()
(что плохо):
public class WcfClient<T> : ClientBase<T>, IDisposable where T : class
{
public new T Channel {get {return base.Channel;}}
void IDisposable.Dispose() {
try {
switch(State) {
case CommunicationState.Open: Close(); break;
// etc
}
} catch {} // swallow it down (perhaps log it first)
}
}
Чтобы вернуть интерфейс из сервиса, вам необходимо использовать атрибут KnownType:
-
Если вы хотите вернуть пользовательский тип из сервиса:
Помогает ли что-нибудь из этого?