WCF C# - 从App.config获取特定配置值

时间:2011-07-20 18:38:34

标签: c# wcf app-config config

我有一个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。但是,实现这一目标很麻烦。

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

4 个答案:

答案 0 :(得分:3)

直接创建频道并不难,并且为您读入所有端点配置。尝试这样的事情:

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();
        }
    }
}

答案 1 :(得分:0)

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 
}

答案 2 :(得分:0)

如果我理解你的问题,那就和我想做的事情类似。我不想在每个需要访问该服务的库或应用程序中包含服务引用。我创建了一个Mediator模式类,它具有服务引用并作为服务的代理。它将端点字​​符串作为唯一的类构造函数参数。构造函数看起来像这样(我把通道工厂示例作为注释)

    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);
    }

我实际上复制了服务中的每个属性(很多时候我有很少的mods使服务更容易被最终客户端使用)但你可能只是违反了客户端代码中的Demeter法则并返回底层服务客户端(上面的代码中的_dspClient)并使用它。

答案 3 :(得分:0)

由于您的所有连接都是相同的合同,并且本质上是相同的客户端代码,因此您可以使用相同的ChannelFactory创建所需数量的ServiceChannel,并且可以连接每个ServiceChannel EndpointAddress 1}}到常规旧应用程序设置或数据库中指定的不同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

您可以根据需要多次执行此操作,使用相同的ServiceChannel,但每次都会创建具有不同端点的新{{1}}。