0

我有两个项目,一个是一组 WCF 服务(我们称之为 P1),另一个是标准 Web 应用程序(P2)。

作为开始,我们将 P2 中的 P1 服务作为 SOAP 服务使用,一切顺利。后来我们注意到,在我们所有的项目部署中,我们将 P1 和 P2 都托管在同一台服务器上。所以我们想为什么要这样保留它 - 意思是:当每个方法在同一服务器上运行时,为什么我们每次都要序列化/反序列化请求/响应。所以我们决定在 P2 中使用 P1 作为标准项目库引用。

我们不得不进行大量修改,因为代理类名称发生了变化,并且每次调用后都必须删除客户端的“关闭”方法。现在,我们有一个新的部署,它将要求 P1 位于与 P2 不同的服务器上,我们可以更改它,并且我们必须再次使用 P1 作为 WCF 服务 - 这意味着整个 P2 上的大量更改并以序列化结束所有其他部署的开销!

问题是,有没有办法对 P1 进行这样的动态引用,因此无论部署在 1 台还是 2 台服务器上都不需要编码?

4

2 回答 2

2

可以使 WCF 服务在本地运行(项目参考)或作为基于 web.config 上的某些键的服务。我做了下面的例子,但我没有测试它,但我之前做过完全相似的事情

在 web 配置中添加密钥说 serviceMode="local/service"

然后说你有wcf服务接口

    [ServiceContract]
    public class ICalculator
    {
         [OperationContract]
        int Add(int x, int y);
    }

执行

  public class Calculator
   {
      public int Add(int x, y)
      {
        return x+y;
      }
}

///现在在您的网络应用程序中

你将会有

   public LocalProxy:ICalculator //this will use direct instance of the Calculator Service
   {
      private ICalculator _calculator

      public  LocalProxy(ICalculator calculator)
      {
        _calculator =calculator;
      }

      public int Add(int x, int y)
      {
         return _calculator.Add(x,y);
      }

}




 public class RemoteProxy:ICalculator  ///This will be real wcf proxy

    {


       public int Add (int x,int y)
       {

          var endpointAddress = new EndpointAddress(EndpointUrl);
           ChannelFactory<ICalculator> factory = null;
           ICalculator calculator ;

          try
          {
             // Just picking a simple binding here to focus on other aspects
             Binding binding = new BasicHttpBinding();

             factory = new ChannelFactory<ICalculator>(binding);
             calculator= factory.CreateChannel(endpointAddress);
             if (calculator== null)
             {
                 throw new CommunicationException(
                    String.Format("Unable to connect to service at {0}", endpointUrl));
             }

             int sum= calculator.Add(x,y);
             ((IClientChannel)calculator).Close();

             calculator = null;
             factory.Close();
             factory = null;

             return sum;
          }
          finally
          {
             if (calculator!= null) ((IClientChannel)calculator).Close();
             if (factory != null) factory.Abort();
          }
       }

    }

现在你如何使用它

 ICalculator _calculatorProxy;

    //get the web config key here, you may use strategy pattern to select between the two proxies


     if(key=="local)
    {
     _calculator= new LocalProxy(new Calculator)
    }
    else
    {
     _calculator= new RemoteProxy();
    }


    //then 
     _calculator.Add(3,5);

注意:在单独的程序集中定义您的接口和数据协定,以便您可以与需要 wcf 作为服务运行的 Web 应用程序共享它。

于 2013-09-06T23:24:25.777 回答
1

您在 P2 中使用来自 P1 的服务的所有组件都应该只使用服务接口(即IMyServiceISomeOtherService。他们不应该关心它是本地实例还是代理,也不应该关闭连接。

实现这一点的最简单(恕我直言)是通过像 Castle Windsor 这样的 IoC 使用依赖注入(这是我唯一熟悉的,但还有其他几个)。容器将负责提供服务接口的实例。您可以提供不同的实现并在运行时使用适当的实现(WCF 服务或本地实例)配置容器。Close()一旦不再需要服务组件(即调用WCF 代理并且不为其他代理做任何事情),容器还将负责处理服务组件。

这是一个很大的话题,所以我建议你在互联网上搜索一些关键词——那里有很多材料。

于 2013-09-06T23:20:08.033 回答