31.03.2009 г.

Loading a custom config file instead of app.config

Today happily I found a solution for the problem explained in a yesterday post in my blog.
The solution is to implement a class that changes the configuration file, associated with the project. Here is some working code doing that:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;

namespace OmeksOfficeTools
{
public class ConfigurationFileChanger : IDisposable
{
private string currentConfigFilePath;
private string newConfigFilePath = @"YourLibraryPathHere";

public ConfigurationFileChanger()
{
currentConfigFilePath = AppDomain.CurrentDomain.GetData("APP_CONFIG_FILE").ToString();
ChangeConfigFile(newConfigFilePath);
}
protected void ChangeConfigFile(string newConfigFilePath)
{
AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", newConfigFilePath);
FieldInfo[] fiStateValues = null;

Type initStateType = typeof(System.Configuration.ConfigurationManager).GetNestedType("InitState", BindingFlags.NonPublic);
if (initStateType != null)
{
fiStateValues = initStateType.GetFields();
}
FieldInfo fiInit = typeof(System.Configuration.ConfigurationManager).GetField("s_initState", BindingFlags.NonPublic | BindingFlags.Static);
FieldInfo fiSystem = typeof(System.Configuration.ConfigurationManager).GetField("s_configSystem", BindingFlags.NonPublic | BindingFlags.Static);
if (fiInit != null && fiSystem != null && null != fiStateValues)
{
fiInit.SetValue(null, fiStateValues[1].GetValue(null));
fiSystem.SetValue(null, null);
}
}

public void Dispose()
{
ChangeConfigFile(currentConfigFilePath);
}
}
}


This really worked for me. I use .Net Framework 3.5 sp1 but I think this will work for .Net Framework 2.0 and above.
The idea is that this code sets the value for app.config path that the framework is going to use and then forces it to reload its configuration by setting 's_initState' to false and 's_configSystem' to null.
The class implements IDisposable to be able to revert to the old configuration file.
So it is good to use the using pattern as follows:
using (ConfigurationFileChanger cfch = new ConfigurationFileChanger())
{
SecurityServiceClient client = new SecurityServiceClient();
//Do your service operation calls here...
}

Where SecurityServiceClient is my service client proxy.

Enjoy :)

P.S. I of course didn't came to that solution while dreaming tonight, so I should give my thanks to the author of THIS article (see also comments under the article).

6 коментара:

  1. Great post. I ran into a problem where the Dispose method got called before the end of the using statement. To fix this you should use a try/finally statement instead of using.

    ОтговорИзтриване
  2. Good post and this mail helped me alot in my college assignement. Gratefulness you as your information.

    ОтговорИзтриване
  3. Да, вероятно така че е

    ОтговорИзтриване
  4. gratefullness, thanks

    I use Addin VS 2008, and has'nt configuration file like Windows Forms or Asp.net.

    The addin is a dll and his config file. If I use WCF (Service reference to external webservice), the config system.servicemodel not found

    I test it in my case...

    ОтговорИзтриване
  5. I think better this:

    private string newConfigFilePath = @"";

    public ConfigurationFileChanger(string newConfigFilePath)
    {
    this.newConfigFilePath = newConfigFilePath; // <=====================

    currentConfigFilePath = AppDomain.CurrentDomain.GetData("APP_CONFIG_FILE").ToString();
    ChangeConfigFile(newConfigFilePath);
    }

    ОтговорИзтриване
  6. I test it like this:

    var addInConfig = System.Configuration.ConfigurationManager.OpenExeConfiguration(System.Reflection.Assembly.GetExecutingAssembly().Location);
    using (var cfch = new ConfigurationFileChanger(addInConfig.FilePath))
    {
    var valorRFC_Number = CalidadCodigo.Integracion.ServiceManager.AbrirPeticion(request);
    }
    but I get the error:

    The type 'Microsoft.ServiceModel.Samples.CustomTextMessageEncodingElement, CalidadCodigo.Integracion.CustomTextEncoder' registered for extension 'customTextMessageEncoding' could not be loaded. (E:\TFS\pro\Main\AddIn\bin\Debug\AddIn.dll.config line 123)

    ОтговорИзтриване