Почему.net WCF Service требует интерфейса

В отличие от реализации 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 ответов

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

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

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

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

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

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

"Преимущество создания ваших служб путем применения ServiceContractAttribute и OperationContractAttribute непосредственно к классу и методам класса, соответственно, заключается в скорости и простоте".

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

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

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

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

Есть и другие причины, но они сразу приходят на ум.

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

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

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

Пробовал с шаблоном службы 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 для доступа к сервису.

Другие вопросы по тегам