wcf从不同的配置文件加载

发布于 2024-10-20 03:12:27 字数 2066 浏览 2 评论 0原文

我试图在与应用程序启动路径不同的路径中使用应用程序配置文件。我发现我可以通过以下方式更改配置文件名:

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

じ违心 2024-10-27 03:12:27

考虑实现自定义 ServiceHostChannelFactory(如果至少要使用一个双工操作,则还需要实现 DuplexChannelFactory)。

您可以将 Configuration 类实例传递给其构造函数,并在必要时使用通过该实例检索的相关部分。

这可能需要比您已经完成的更多的工作,但是使用这样的代码肯定会更整洁:

// Use path to relevant configuration file
string configPath = null;
Configuration config = ConfigurationManager.OpenExeConfiguration( configPath );
CustomServiceHost host = new CustomServiceHost( typeof( Service ), config );
host.Open();

Consider implementing custom ServiceHost and ChannelFactory<TChannel> (and DuplexChannelFactory<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:

// Use path to relevant configuration file
string configPath = null;
Configuration config = ConfigurationManager.OpenExeConfiguration( configPath );
CustomServiceHost host = new CustomServiceHost( typeof( Service ), config );
host.Open();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文