wcf从不同的配置文件加载
我试图在与应用程序启动路径不同的路径中使用应用程序配置文件。我发现我可以通过以下方式更改配置文件名:
AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", NewConfigFullFilename);
在此之后,一些方法可以正常工作,例如。 ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None)
加载正确的文件,其他方法不起作用,例如。 ConfigurationManager.GetSection("system.serviceModel/client")
不会从文件加载该部分。
我发现这个是因为我需要使用配置文件创建服务或通道工厂。写作:
channelFactory = new ChannelFactory<TContract>(EndpointConfigurationName);
我崩溃了,因为我想,内部代码使用了 GetSection 方法。我查看了 ConfigurationManager 类中的私有字段,发现 ClientConfigPaths 的实例在 _applicationCongiUri 字段中具有旧的配置文件名,而静态 s_current 字段具有正确的文件名。我使用下面的代码通过反射正确更改了 2 个字段和此工作的值,从新的配置文件加载服务:
AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", NewConfigFullFilename);
FieldInfo field = typeof(ConfigurationManager).GetField("s_initLock", BindingFlags.Static | BindingFlags.NonPublic);
object lockobj = field.GetValue(null);
lock (lockobj)
{
typeof(ConfigurationManager).GetField("s_initState", BindingFlags.NonPublic | BindingFlags.Static).SetValue(null, 0);
}
field = typeof(ConfigurationManager).GetField("s_configSystem", BindingFlags.Static | BindingFlags.NonPublic);
object s_configSystem = field.GetValue(null);
field = s_configSystem.GetType().GetField("_configHost", BindingFlags.Instance | BindingFlags.NonPublic);
object _configHost = field.GetValue(s_configSystem);
field = _configHost.GetType().GetField("_configPaths", BindingFlags.Instance | BindingFlags.NonPublic);
object _configPaths = field.GetValue(_configHost);
field = _configPaths.GetType().GetField("_applicationConfigUri", BindingFlags.Instance | BindingFlags.NonPublic);
field.SetValue(_configPaths, NewConfigFullFilename);
field = _configPaths.GetType().GetField("_localConfigFilename", BindingFlags.Instance | BindingFlags.NonPublic);
field.SetValue(_configPaths, NewConfigFullFilename);
现在我想知道是否还有其他方法可以这样做,或者这是否是一个错误AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE"
还不够,或任何其他建议。
谢谢
I'm trying to use an application config file in a path different from the application startup path. I found I can change the config file name with:
AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", NewConfigFullFilename);
After this some methods work correctly, for ex. ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None)
loads the right file, other methods don't work, for ex. ConfigurationManager.GetSection("system.serviceModel/client")
does not load the section from the file.
I found this because I need to create services or channel factories using the config file. Writing:
channelFactory = new ChannelFactory<TContract>(EndpointConfigurationName);
I have a crash because, I suppose, the internal code uses the GetSection method. I looked at private fields in the ConfigurationManager class and I found that the instance of the ClientConfigPaths has the old config file name in _applicationCongiUri field while the static s_current field has the right file name. I used the foolowing code to change with reflection the values of 2 fields and this wortk correctly, loading the services from the new config file:
AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", NewConfigFullFilename);
FieldInfo field = typeof(ConfigurationManager).GetField("s_initLock", BindingFlags.Static | BindingFlags.NonPublic);
object lockobj = field.GetValue(null);
lock (lockobj)
{
typeof(ConfigurationManager).GetField("s_initState", BindingFlags.NonPublic | BindingFlags.Static).SetValue(null, 0);
}
field = typeof(ConfigurationManager).GetField("s_configSystem", BindingFlags.Static | BindingFlags.NonPublic);
object s_configSystem = field.GetValue(null);
field = s_configSystem.GetType().GetField("_configHost", BindingFlags.Instance | BindingFlags.NonPublic);
object _configHost = field.GetValue(s_configSystem);
field = _configHost.GetType().GetField("_configPaths", BindingFlags.Instance | BindingFlags.NonPublic);
object _configPaths = field.GetValue(_configHost);
field = _configPaths.GetType().GetField("_applicationConfigUri", BindingFlags.Instance | BindingFlags.NonPublic);
field.SetValue(_configPaths, NewConfigFullFilename);
field = _configPaths.GetType().GetField("_localConfigFilename", BindingFlags.Instance | BindingFlags.NonPublic);
field.SetValue(_configPaths, NewConfigFullFilename);
Now I'd like to know if there are other ways to do so, or if it is a bug that the AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE"
is not enough, or any other suggestion.
Thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
考虑实现自定义
ServiceHost
和ChannelFactory
(如果至少要使用一个双工操作,则还需要实现DuplexChannelFactory
)。您可以将
Configuration
类实例传递给其构造函数,并在必要时使用通过该实例检索的相关部分。这可能需要比您已经完成的更多的工作,但是使用这样的代码肯定会更整洁:
Consider implementing custom
ServiceHost
andChannelFactory<TChannel>
(andDuplexChannelFactory<TChannel>
if there is at least one duplex operation to be used).You could pass
Configuration
class instance to their constructors and use relevant sections retrieved via that instance when necessary.This might require more work than you have already done, but code would surely be more neater with something like this: