【问题标题】:WCF C# - Getting Specific Configuration Values From App.configWCF C# - 从 App.config 获取特定的配置值
【发布时间】:2011-10-09 15:44:02
【问题描述】:

我有一个 WCF 服务 XYZ,它将部署在多个主机上。每个这样的服务都可以连接到部署在其他主机之一上的另一个 XYZ 服务。这是一个分布式系统,服务之间的状态会有所不同。

为了进行通信,在 Visual Studio 中“添加服务引用”对我来说并没有什么意义,因为这只会增加冗余(服务已经知道它将与什么进行通信)。

所以目前我的想法是在每个服务的 App.config 文件中指定其他服务端点。例如:

<client>
  <endpoint name="BEL" 
            address="tcp://us.test.com:7650/OrderManagementService"
            binding="tcpBinding"
            contract="IOrderManagementService"/>
  <endpoint name="BEL2"
      address="tcp://us.test2.com:7650/OrderManagementService"
      binding="tcpBinding"
      contract="IOrderManagementService"/>
</client>

现在,我只想要一种方法来读取这些设置并在我的代码中创建 ChannelFactories 和 Channels。但是,这样做很麻烦。

两个问题:我做的对吗?如果是这样,从配置文件中提取这些值的最佳方法是什么?

【问题讨论】:

标签: c# wcf app-config config


【解决方案1】:

直接创建通道并不难,所有端点配置都已为您读入。试试这样的:

var factory = new ChannelFactory<IOrderManagementService>("BEL");
var proxy = factory.CreateChannel();
// call methods on proxy
proxy.Close();

请注意,代理需要在完成后立即正确关闭(这意味着正确调用CloseAbort)。但是,您可以让工厂长时间处于打开状态,即使在缓存中也是如此。

您可以将其封装到辅助方法中以使调用代码简单:

public static ChannelFactory<TContract> NewChannelFactory<TContract>(string endpointConfigurationName) where TContract : class {
    // TODO: Cache the factory in here for better performance.
    return new ChannelFactory<TContract>(endpointConfigurationName);
}

public static void Invoke<TContract>(ChannelFactory<TContract> factory, Action<TContract> action) where TContract : class {
    var proxy = (IClientChannel) factory.CreateChannel();
    bool success = false;
    try {
        action((TContract) proxy);
        proxy.Close();
        success = true;
    } finally {
        if(!success) {
            proxy.Abort();
        }
    }
}

【讨论】:

  • 谢谢,我不知道端点配置是自动为我读入的!
  • 奇怪的表述 - 为什么不直接捕获异常,中止通道并重新抛出?
  • @Richard:捕获并重新抛出异常需要时间,并且会删除部分堆栈跟踪。如果这些事情与您的代码无关,那很好,但避免这种情况不需要任何成本。
  • 虽然速度较慢,但​​这是您希望很少执行的代码路径,并且代码的意图非常明确。如果使用通用 throw 子句,则不会丢失任何信息
  • Close 可以像其他代码一样轻松抛出异常。如果发生这种情况,您仍然希望调用 Abort。如果您不使用上述模式,则需要两个嵌套的 catch 块,这对我来说似乎更丑。
【解决方案2】:

WebConfigurationManager 可用于获取您的端点。您有一个客户端部分,因此在 GetSection 中只需像上面的代码一样传递它。

ClientSection clientSection = (WebConfigurationManager.GetSection("system.serviceModel/client") as ClientSection);

foreach(ChannelEndpointElement cee in clientSection.Endpoints)
{
    // Store your endpoint for future use with ChannelFactories 
}

【讨论】:

    【解决方案3】:

    如果我正确理解了您的问题,这与我想做的事情相似。我不想在需要访问服务的每个库或应用程序中包含服务引用。我创建了一个具有服务引用并充当服务代理的中介模式类。它将端点字​​符串作为唯一的类构造函数参数。构造函数看起来像这样(我在评论中添加了一个通道工厂示例)

        public DspServiceMediator( String serviceAddress)
        {
            EndpointAddress end_point = new EndpointAddress(serviceAddress);
            NetTcpBinding new_tcp = new NetTcpBinding(SecurityMode.None);
            new_tcp.ReceiveTimeout = TimeSpan.MaxValue;
            new_tcp.SendTimeout = new TimeSpan(0, 0, 30); //30 seconds
            //_channelFactory = new ChannelFactory<DspServiceClient>(new_tcp, end_point);
            _dspClient = new DspServiceClient(new_tcp, end_point);
        }
    

    我实际上复制了服务中的每个属性(很多时候我有一些小模块使最终客户端更容易使用该服务)但是您可以在客户端代码中违反 Demeter 法则并返回底层服务客户端( _dspClient 在上面的代码中)并使用它。

    【讨论】:

      【解决方案4】:

      由于您的所有连接都是相同的合约,并且本质上是相同的客户端代码,因此您可以使用相同的ChannelFactory 创建任意数量的ServiceChannel,并且可以将每个ServiceChannel 连接到不同的@ 987654324@es 在常规旧应用程序设置或数据库中指定:

      private List<string> _endpointLists = new List<string>() { "127.0.0.0:1234" };
      private static ChannelFactory<IWCFServiceChannel> _channelFactory = new ChannelFactory<ServiceReference.IWCFServiceChannel>("App.config Binding Name Here");
      private List<WCFServiceChannel> _serviceChannels = new List<WCFServiceChannel>();
      
      foreach (string uriEndpoint in _endpointLists)
          _serviceChannels.Add(_channelFactory.CreateChannel(new EndpointAddress(uriEndpoint)));
      
      _serviceChannels[0].Open();
      ...
      

      您可以根据需要多次执行此操作,使用相同的ChannelFactory,但每次都使用不同的端点创建新的ServiceChannels。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-06-21
        • 2014-10-11
        • 2011-06-30
        • 1970-01-01
        • 1970-01-01
        • 2016-05-02
        • 2012-04-24
        • 2010-10-15
        相关资源
        最近更新 更多