Подтвердить что ты не робот

Почему .NET-служба WCF требует интерфейса

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

4b9b3361

Ответ 1

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

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

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

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

Ответ 2

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

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

"Преимущество создания ваших сервисов путем применения ServiceContractAttribute и OperationContractAttribute непосредственно к классу и методам в классе, соответственно, - это скорость и простота".

Ответ 3

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

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

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

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

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

Ответ 4

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

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

Ответ 5

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

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