WCF C# - 从 App.config 获取特定的配置值
Posted
技术标签:
【中文标题】WCF C# - 从 App.config 获取特定的配置值【英文标题】:WCF C# - Getting Specific Configuration Values From 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。但是,这样做很麻烦。
两个问题:我做的对吗?如果是这样,从配置文件中提取这些值的最佳方法是什么?
【问题讨论】:
这个问题***.com/questions/297431/… 可能有帮助 【参考方案1】:直接创建通道并不难,所有端点配置都已为您读入。试试这样的:
var factory = new ChannelFactory<IOrderManagementService>("BEL");
var proxy = factory.CreateChannel();
// call methods on proxy
proxy.Close();
请注意,代理需要在完成后立即正确关闭(这意味着正确调用Close
或Abort
)。但是,您可以让工厂长时间处于打开状态,即使在缓存中也是如此。
您可以将其封装到辅助方法中以使调用代码简单:
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
,但每次都使用不同的端点创建新的ServiceChannel
s。
【讨论】:
以上是关于WCF C# - 从 App.config 获取特定的配置值的主要内容,如果未能解决你的问题,请参考以下文章
从 c# 中的 app.config 获取 ConnectionString [重复]