zoukankan      html  css  js  c++  java
  • 在WCF程序中动态修改app.config配置文件

    今天在个WCF程序中加入了修改配置文件的功能。我是直接通过IO操作修改的app.config文件内容,修改后发现发现其并不生效,用Google搜了一下,在园子里的文章动态修改App.Config 和web.Config中找到了解决方案。

    原来,.net framework中对于配置文件不是实时读取的,而是有缓存的。对于那些已经更新了的内容,需要调用ConfigurationManager.RefreshSection(需要添加System.Configuration.dll的引用)函数刷新相应节点。

    比较蛋疼的是,这个函数并不支持刷新Group。也就是说,我们不能通过ConfigurationManager.RefreshSection("system.serviceModel")一句话实现对WCF的配置刷新,需要调用如下四句话才行。

    ConfigurationManager.RefreshSection("system.serviceModel/behaviors");
    ConfigurationManager.RefreshSection("system.serviceModel/bindings");
    ConfigurationManager.RefreshSection("system.serviceModel/client");
    ConfigurationManager.RefreshSection("system.serviceModel/services");

    另外,值得一提的是:如果用IO操作修改修改app.config配置,直接使用相对路径"myapp.exe.config"来修改不可靠的,很容易出现找不到配置文件的异常(原因有很多种),需要使用AppDomain.CurrentDomain.SetupInformation.ConfigurationFile属性来获取配置文件的完整路径。

    假设XXX.exe.config内容如下

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <system.serviceModel>
        <bindings>
          <basicHttpBinding>
            <binding name="ProcessServiceSoap" />
          </basicHttpBinding>
        </bindings>
    
        <client>
          <endpoint address="http://192.168.0.123/Services/ProcessService.asmx"
              binding="basicHttpBinding" bindingConfiguration="ProcessServiceSoap"
              contract="S_ProcessService.ProcessServiceSoap" name="ProcessServiceSoap" />
        </client>
      </system.serviceModel>
    </configuration>

    以下方法,修改 endpoint 下指定根据 bindingConfiguration 的值修改 address

    public void ChangeEndpointAddress(string endpointBindingConfiguration, string address)
    {
        var config = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
        XElement root = XElement.Load(config);
    
        var quary = from ele in root.Element("system.serviceModel").Element("client").Elements("endpoint") where ele.Attribute("bindingConfiguration").Value == endpointBindingConfiguration select ele;
        quary.ElementAt(0).SetAttributeValue("address", address);
    
        //保存上面的修改    
        root.Save(config);
        ConfigurationManager.RefreshSection("system.serviceModel/client");
    }

    如 ChangeEndpointAddress("ProcessServiceSoap", "http://192.168.111.222/Services/ProcessService.asmx")

    将原来的address192.168.0.123修改为192.168.111.222

    首先假设你的应用程序配置文件如下:

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <appSettings>
        <add key="name" value="old"/>
      </appSettings>
    </configuration> 

    Ok,那么如何在运行时去修改name的值呢??

    有很多童鞋会说可以使用Xml读取配置文件,然后xxx。。。。

    当然这种方法肯定可以解决问题,有没有其他方法呢??

    在这里我要介绍一种比较简单的方法,可能已经有人知道了,那就是使用ConfigurationManager类

    ConfigurationManager 存在System.Configuration.dll 中。

    代码如下:

    public static void Main()
    {
        Console.WriteLine(ConfigurationManager.AppSettings["name"]);
        ChangeConfiguration();
        Console.WriteLine(ConfigurationManager.AppSettings["name"]);
        Console.ReadLine();
    }
    
    private static void ChangeConfiguration()
    {
        //读取程序集的配置文件
        string assemblyConfigFile = Assembly.GetEntryAssembly().Location;
    
        Configuration config = ConfigurationManager.OpenExeConfiguration(assemblyConfigFile);
        //获取appSettings节点
        AppSettingsSection appSettings = (AppSettingsSection)config.GetSection("appSettings");
       
    
        //删除name,然后添加新值
        appSettings.Settings.Remove("name");
        appSettings.Settings.Add("name", "new");
    
        //保存配置文件
        config.Save();
    }

    代码很简单:首先读取配置文件,接着获取appSettings节点,然后修改,接着保存。 运行:结果如下:

    可以看到输出的值是两个old.

    为什么??

     

    查找msdn文档可以发现微软出于性能考虑,对ConfigurationManager采用了缓存策略,所以如果要读取新的值,应该使用ConfigurationManager的RefreshSection来进行刷新,

    ConfigurationManager . RefreshSection:

    刷新命名节,这样在下次检索它时将从磁盘重新读取它。

    于是将Main方法修改为:

     

    Console.WriteLine(ConfigurationManager.AppSettings["name"]);
    
    ChangeConfiguration();
    
    ConfigurationManager.RefreshSection("appSettings");
    
     
    Console.WriteLine(ConfigurationManager.AppSettings["name"]);

    重新清理解决方案,重新运行:

    可以看到,仍然是两个old。。。

    为什么??  

    难道值没有修改??,我们打开应用程序的配置文件,可以通过监视assemblyConfigFile获得路径

    上面是xxxinDebugCAStudy.exe.,对应的配置文件就是CAStudy.exe.config

     

    文件的内容如下:

    可以发现value 值已经更改,那么为什么输出还是old,old 呢??

     

    为了验证不是VS2010的问题。

    首先手动将CAStudy.exe.config 文件中的value改为”old”,接着再次运行CAStudy.exe 结果如下:

    可以看到输出时old,和new。为什么会这样???

     

    难道调试时读取的不是修改的配置文件,或者修改的配置文件并不是调试的应用程序读取的文件??

    在assemblyConfigFile 中设置断点,可以发现assemblyConfigFile 读取的是CAStudy.exe.Config。但是vs调试的时候运行的是CAStudy.vshost.exe。也就是说我们使用ConfigurationManager.OpenExeConfiguration 打开的是CAStudy.exe.config文件,但是我们调试的应用程序CAStudy.vshost.exe使用的是CAStudy.vshost.exe.config文件。

    那么还有其他的方式可以准确的获取应用程序配置文件吗??

    有的,使用AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;

    将ChangeConfiguration()方法修改如下:

    public static void Main()
    {
        Console.WriteLine(ConfigurationManager.AppSettings["name"]);
        ChangeConfiguration();
        Console.WriteLine(ConfigurationManager.AppSettings["name"]);
        Console.ReadLine();
    }
    
    private static void ChangeConfiguration()
    {
        //读取程序集的配置文件
        string assemblyConfigFile = Assembly.GetEntryAssembly().Location;
    
        Configuration config = ConfigurationManager.OpenExeConfiguration(assemblyConfigFile);
        //获取appSettings节点
        AppSettingsSection appSettings = (AppSettingsSection)config.GetSection("appSettings");
       
    
        //删除name,然后添加新值
        appSettings.Settings.Remove("name");
        appSettings.Settings.Add("name", "new");
    
        //保存配置文件
        config.Save();
    }

    清理,重新运行:

    使用默认的不传递字符串的版本就可以打开当前配置文件了。

    Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);

    如果要查看当前配置文件的完整路径可以使用AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;

    重新运行,结果如下:

    参考

    https://blogs.msdn.microsoft.com/youssefm/2010/01/21/how-to-change-net-configuration-files-at-runtime-including-for-wcf/

    http://developer.51cto.com/art/200908/146303.htm

    http://www.codeproject.com/Articles/14744/Read-Write-App-Config-File-with-NET

  • 相关阅读:
    【LeetCode】048. Rotate Image
    【LeetCode】036. Valid Sudoku
    【LeetCode】060. Permutation Sequence
    【LeetCode】001. Two Sum
    【LeetCode】128. Longest Consecutive Sequence
    【LeetCode】081. Search in Rotated Sorted Array II
    【LeetCode】033. Search in Rotated Sorted Array
    顺时针打印矩阵
    矩形覆盖
    二维数组中的查找
  • 原文地址:https://www.cnblogs.com/code1992/p/11353053.html
Copyright © 2011-2022 走看看