【问题标题】:Why does .net WCF Service require the Interface为什么 .net WCF 服务需要接口
【发布时间】:2011-03-02 15:48:32
【问题描述】:

与 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 的接口?

【问题讨论】:

    标签: .net wcf c#-4.0 polymorphism


    【解决方案1】:

    不,WCF 不要求您拥有一个接口并实现它。

    这只是普遍接受的最佳实践 - 但如果您不想这样做,则不必必须

    如果您愿意,您可以将您的 [ServiceContract] 放在具有许多 [OperationContract] 服务方法的具体类上 - 没有什么能阻止您这样做。

    但同样:使用接口将实际合约分离为接口是普遍接受和宣扬的最佳实践(因此您可以模拟它以进行测试等)。

    【讨论】:

    • 其实,至少有一件事阻止了你:继承。您可以在从多个接口继承的接口上应用 [ServiceContract],同时应用 [ServiceContract],使服务合同模块化。如果您将 [ServiceContract] 应用到一个类,它既不能继承也不能被继承 - 您会被类本身定义的任何契约所困扰。
    【解决方案2】:

    实际上,即使是 MSDN 也不时承认接口的形式可能并不总是“正确的做法”:

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

    “通过将 ServiceContractAttribute 和 OperationContractAttribute 分别直接应用于类和类上的方法来创建服务的优点是速度和简单性。”

    【讨论】:

      【解决方案3】:

      可以在不使用接口的情况下创建 WCF 服务:

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

      也就是说,建议将它们分开。将合同与实施分开可以为您带来一些不同的优势:

      • 您可以将接口放入单独的程序集中。任何需要了解接口的代码都可以使用这个程序集,但不一定要了解实现。我有时会使用它来构建一种服务网关,将与服务的通信包装起来。
      • 您可以让一个类实现多个接口。这意味着您可以使用 WCF 端点中的不同接口以不同方式公开相同的实现类。

      还有其他原因,但这些原因会立即浮现在脑海中。

      【讨论】:

        【解决方案4】:

        in dotnet 接口用于描述行为。 WCF、Web 服务和远程处理这一切技术都使用 RPC(远程过程调用)行为。 在 RPC 中,必须有一些由客户端和服务器共享的公共绑定。

        如果您使用类而不是接口,您也已将生成的 dll 文件共享给客户端。 因此您的逻辑转到客户端,这不是一个好习惯。这就是我们使用接口的原因。

        【讨论】:

          【解决方案5】:

          如果您创建的服务没有接口,那么您将无法在代码中动态创建通道。那么您访问该服务的唯一方法就是添加一个服务引用。

          尝试使用默认的 VS 2015 WCF 服务模板;用 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
          

          然后下面的代码运行没有任何问题。现在请在创建 ChannelFactory 对象时将 Service1 替换为 IService1 接口。

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

          如果您的客户端使用 ChannelFactory 而不是 ServiceReference 来访问服务,这是最重要的方面。

          【讨论】:

          • 几篇文章可能会有很长的路要走......认真。没有
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-01-01
          • 2011-05-13
          • 1970-01-01
          • 1970-01-01
          • 2016-12-29
          • 1970-01-01
          相关资源
          最近更新 更多