如何在运行时更新配置文件中的assemblyBinding部分?

Jul*_*rau 9 .net c# configuration

我正在尝试动态更改程序集绑定(从一个版本到另一个版本).

我试过这段代码,但它不起作用:

      Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
      ConfigurationSection assemblyBindingSection = config.Sections["assemblyBinding"];

      assemblyBindingSection.SectionInformation.ConfigSource = "bindingConf.xml";
      config.Save(ConfigurationSaveMode.Modified);

      ConfigurationManager.RefreshSection("assemblyBinding");
Run Code Online (Sandbox Code Playgroud)

bindingConf.xml含有assemblyBinding部配置.

那么可以在运行时更改此部分吗?怎么做?我有什么替代品?

Eri*_*ger 19

我发现动态绑定到不同版本的程序集的最好方法是挂钩AppDomain.AssemblyResolve事件.只要运行时无法找到应用程序链接的确切程序集,就会触发此事件,并且它允许您在其位置提供另一个自己加载的程序集(只要它是兼容的).

例如,您可以在应用程序的主类上放置一个静态构造函数来挂钩事件,如下所示:

using System.Reflection;

static Program()
{
    AppDomain.CurrentDomain.AssemblyResolve += delegate(object sender, ResolveEventArgs e)
    {
        AssemblyName requestedName = new AssemblyName(e.Name);

        if (requestedName.Name == "AssemblyNameToRedirect")
        {
            // Put code here to load whatever version of the assembly you actually have

            return Assembly.LoadFrom("RedirectedAssembly.DLL");
        }
        else
        {
            return null;
        }
    };
}
Run Code Online (Sandbox Code Playgroud)

此方法避免了处理配置文件中的程序集绑定的需要,并且就您可以使用它执行的操作而言更灵活一些.

  • 很好的解决方案!不幸的是,就我而言,即使默认程序集已解析,我也需要绑定。所以该事件永远不会被解雇。 (2认同)

Jos*_*uch 5

我喜欢埃里克的回答。当尝试将新的有缺陷的 NuGet PackageReference 模型与 Web 应用程序一起使用时,它是一个救星。问题是您可以让 msbuild 自动生成绑定,但是它们会生成到 Assembly.dll.config 的绑定,而不是到 web.config 的绑定。所以这个解决方法很棒。

我对 Eric 的代码进行了一些修改,使其更加通用并可与 ASP.Net Core 应用程序一起使用:

AppDomain.CurrentDomain.AssemblyResolve += delegate (object sender2, ResolveEventArgs e2)
            {
                var requestedNameAssembly = new AssemblyName(e2.Name);
                var requestedName = requestedNameAssembly.Name;
                if (requestedName.EndsWith(".resources")) return null;
                var binFolder = System.Web.Hosting.HostingEnvironment.MapPath("~/bin");
                var fullPath = Path.Combine(binFolder, requestedName) + ".dll";
                if (File.Exists(fullPath))
                {
                    return Assembly.LoadFrom(fullPath);
                }

                return null;
            };
Run Code Online (Sandbox Code Playgroud)