Ссылка на службу WCF генерирует собственный интерфейс контракта, не будет повторно использовать мой

мой первый вопрос, поэтому надеюсь, что это подходит:

сборка общего интерфейса - у меня есть "общая" сборка, которая имеет интерфейс, назовем ее IDocRepository. Он помечен [ServiceContract] и несколько [OperationContract]-отмечены методов.

сборки реализации WCF - у меня есть два проекта службы WCF, каждый из которых ссылается на общую сборку, каждый из которых реализует этот интерфейс как службу WCF.

потребитель собрание - наконец, у меня есть проект "клиент", также ссылающийся на общую сборку со ссылкой на каждую из двух служб WCF.

однако ссылки на службы, созданные в сборке потребителя, происходят из автоматически сгенерированной версии интерфейса:

public partial class ExampleClient : System.ServiceModel.ClientBase<SomeNamespace.ExampleSvcRef.IDocRepository>, SomeNamespace.ExampleSvcRef.IDocRepository {

то, что я ожидал
Я бы надеялся, что обе ссылки вместо этого автоматически унаследуют интерфейс, который я определил, что сборка consumer / client также ссылающийся. Похоже на повторное использование классов, которые он предоставляет для типов параметров и возвращаемых значений, но для интерфейса службы.

почему
Чтобы я мог создать экземпляр любого прокси-сервера ссылки на службу и привести его к моему типу интерфейса.

таким образом, я мог бы изменить сгенерированный код вручную каждый раз, но должен быть лучший способ...?

(edit: у меня есть "типы повторного использования в ссылочных сборках" и " типы повторного использования во всех ссылках параметры сборок, выбранные для обеих ссылок на службы)

4 ответов


"повторное использование типов в ссылочных сборках" позволяет использовать только контракты данных, а не контракты на обслуживание. Если вы хотите поделиться сервисными контрактами, вам вообще не нужно использовать "добавить ссылку на сервис". Вы можете просто использовать фабрики channelfactory напрямую.

// Supply the binding and address in code
Binding binding = new BasicHttpBinding();
EndpointAddress address = new EndpointAddress("http://tempuri.org/address");
IServiceContract channel = ChannelFactory<IServiceContract>.CreateChannel(binding, address);

// Or read them from the config file
ChannelFactory<IServiceContract> channelFactory = new ChannelFactory<IServiceContract>();
IServiceContract channel = channelFactory.CreateChannel();

объект канала также будет реализовывать ICommunicationObject, поэтому вы можете бросить его, если вам нужно вызвать методы, такие как Open() или Close().


когда вы создаете ссылку на службу, есть поле, которое вы можете отметить, чтобы сделать его повторно использовать общие определения. Убедитесь, что клиентский проект уже ссылается на общую сборку, снова добавьте ссылку на службу и внимательно проверьте все параметры.

Если он все еще не работает, проверьте привязки вы используете. У меня есть смутное воспоминание, что базовая привязка HTTP не будет поддерживать повторное использование типов?


есть еще один хороший вариант, если вы хотите продолжать использовать генератор прокси для общества-но-несколько полезных функций... Используйте частичный класс:

namespace <same namespace as generated proxy>
{
    public partial class MyClient : <namespace of "real" service contract>.IServiceContract
    {
    }
}

убедитесь, что прокси-сервер генерирует код так же, как определяет его контракт службы, то есть, если он использует "список", используйте эту опцию в Configure Service References. Другими словами, убедитесь, что созданный интерфейс службы точно соответствует реальному интерфейсу службы и приведенному выше коду должно работать, и для обновления ссылки вы используете щелчок правой кнопкой мыши вместо написания кода.


Visual Studio не поддерживает повторное использование существующего интерфейса при создании прокси-классов для вас. Повторно использовать типы не будут использовать интерфейс контракта как Quartermeister указал.

мы решили его наследства. Очень похоже на идею частичного класса выше, предложенную Jester Software.

вот как мы ее решили:

в проекте вашего клиента просто создайте ссылку на службу, как вы это сделали бы. Затем добавьте класс, который служит заменой для клиента:

internal class MyServiceProxy : MyServiceClient, MyLogicNamespace.IMyService
{}

этот класс наследуется от сгенерированного MyServiceClient, но заявляет, что этот клиент реализует исходный интерфейс.

(Я предлагаю вам поместить их в папку с именем "ServiceProxies")

Если класс MyServiceClient содержит методы, не соответствующие исходному интерфейсу, вы можете добавить их в этот прокси-сервер и выполнить преобразование в коде.

после этого, просто используйте MyServiceProxy, где вы бы использовали MyServiceClient.