wcf loaded from different 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:开发者_StackOverflow
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
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();
精彩评论