Почему .net WCF Service требует интерфейса - PullRequest
12 голосов
/ 02 марта 2011

В отличие от реализации asmx, wcf требует от вас реализации его интерфейса.Я не совсем понимаю причину этого дизайна.Интерфейс - это контракт между 2 классами ... С учетом сказанного, как часто у вас есть 2 службы wcf, которые удовлетворяют одному и тому же интерфейсу, но реализуются по-разному?

Другой комментарий, msdn настоятельно рекомендует сделать это:

   MyService service = new MyService();

   try {

      service.DoWork();

   }
   catch(Exception) {}
   finally {
      service.Close();
   }

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

   public MyComponent : IDisposable
   {

       readonly IMyService service = null;

       public MyComponent(IMyService service) {

           this.service = service;

       }

       public DoWork() 
       {
           //some additional code.
           this.service.DoWork();

       }

       public void Dispose() 
       {
           //The Interface does not have the Close method,
           //So doing this defeats the whole purpose of polymorphysm
           (this.service as MyService).Close(); //Silly.
       }
   } 

Как вы используете преимущество интерфейса с WCF?

Ответы [ 5 ]

24 голосов
/ 02 марта 2011

Нет, WCF НЕ требует , чтобы вы имели интерфейс и реализовали его.

Это просто общепринятая лучшая практика , чтобы сделать это - но вам не нужно , если вы не хотите.

Если вы хотите, вы можете поместить [ServiceContract] в конкретный класс, который имеет ряд [OperationContract] методов обслуживания - ничто не мешает вам сделать это.

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

9 голосов
/ 04 мая 2011

На самом деле, даже MSDN время от времени допускает, что формальность интерфейсов не всегда может быть «правильной»:

http://msdn.microsoft.com/en-us/library/ms733070.aspx

«Преимущество создания вашегоСлужбы путем применения ServiceContractAttribute и OperationContractAttribute непосредственно к классу и к методам класса соответственно - это скорость и простота. "

6 голосов
/ 02 марта 2011

Вы можете создать службу WCF без использования интерфейса:

[ServiceContract]
public class TheService
{
   // more stuff here
}

При этом рекомендуется их разделять.Отделение контракта от реализации может дать вам различные преимущества:

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

Существуют и другие причины, но они сразу приходят на ум.

1 голос
/ 08 января 2017

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

Пробовал со стандартным шаблоном службы WCF VS 2015; помечает класс обслуживания с помощью ServiceContract и методы с атрибутом OperationContract . Реализация интерфейса IService1 удалена (реализация интерфейса отсутствует).

[ServiceContract]
public class Service1
{
    [OperationContract]
    public string GetData(int value)
    {
        return string.Format("You entered: {0}", value);
    }

    [OperationContract]
    public CompositeType GetDataUsingDataContract(CompositeType composite)
    {
        if (composite == null)
        {
            throw new ArgumentNullException("composite");
        }
        if (composite.BoolValue)
        {
            composite.StringValue += "Suffix";
        }
        return composite;
    }
}

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

    BasicHttpBinding myBinding = new BasicHttpBinding();
    EndpointAddress myEndpoint = new      EndpointAddress("http://localhost:59420/Service1.svc");
    // InvalidOperationException is thrown as below line
    // Error message "The type argument passed to the generic ChannelFactory class must be an interface type"
    ChannelFactory<Service1> myChannelFactory = new ChannelFactory<Service1>(myBinding, myEndpoint);
    // Create a channel.
    Service1 wcfClient1 = myChannelFactory.CreateChannel();
    Console.WriteLine(wcfClient1.GetData(1));
    Console.ReadKey();

Если мы используем и реализуем интерфейс, как показано ниже

public class Service1 : IService1

тогда код ниже работает без проблем. Пожалуйста, теперь Service1 теперь заменяется интерфейсом IService1 при создании объекта ChannelFactory.

ChannelFactory<IService1> myChannelFactory = new ChannelFactory<IService1>(myBinding, myEndpoint);

Это наиболее важный аспект, если ваш клиент использует ChannelFactory вместо ServiceReference для доступа к службе.

1 голос
/ 13 января 2013

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

если вы используете классы вместо интерфейса, вы также делитесь своим результирующим dll-файлом с клиентомследовательно, ваша логика переходит на сторону клиента, что не является хорошей практикой.Вот почему мы используем интерфейсы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...