如何使动态加载的程序集中的设置提供程序可用于反射?

Pét*_*rök 7 c# reflection .net-assembly settingsprovider

这个问题之后,我在我们正在开发的旧版C#应用程序中成功创建了自定义设置提供程序.它通过SettingsProvider属性引用:

public sealed class MySettings : SettingsProvider
{
    ...
}

[SettingsProvider(typeof(MySettings))]
internal sealed partial class Settings {}
Run Code Online (Sandbox Code Playgroud)

但是,现在我遇到了另一个问题.

我们的客户端应用程序包含一个autoupdate工具,它的实现使得大部分客户端 - 包括上面的类 - 都构建在一个DLL中(我们在这里称之为client.dll),然后由EXE使用.如果需要,EXE首先检查更新并从更新服务器下载最新的更新,用其较新版本(包括client.dll)替换所有DLL等.为了能够在运行时替换DLL,它无法静态链接到它们.所以在更新之后,它加载client.dll并像这样运行它:

Assembly assy = Assembly.LoadFile(
        AppDomain.CurrentDomain.BaseDirectory + "client.dll");
object frm = assy.CreateInstance("Client.Forms.MainForm");
Application.Run((Form)frm);
Run Code Online (Sandbox Code Playgroud)

这样做的不幸结果是框架无法在动态加载的程序集中找到我的自定义设置提供程序类.我尝试使用LoadFrom而不是LoadFile上面但它没有帮助.到目前为止,我发现的唯一可行的解​​决方案是在loader exe中实现一个与真实设置提供程序同名的代理类,框架可以找到它.然后,代理从客户端程序集中实例化实际设置提供程序,并委派对它的所有调用.

这似乎有效但我不满意.有没有办法帮助框架直接在动态加载的程序集中查找我的类?

更新

我收到的错误消息:

System.Configuration.ConfigurationErrorsException: Failed to load provider type: Client.Properties.MySettings, Client, Version=4.0.1341.0, Culture=neutral, PublicKeyToken=null.
   at System.Configuration.ApplicationSettingsBase.get_Initializer()
   at System.Configuration.ApplicationSettingsBase.CreateSetting(PropertyInfo propInfo)
   at System.Configuration.ApplicationSettingsBase.EnsureInitialized()
   at System.Configuration.ApplicationSettingsBase.get_Properties()
   at System.Configuration.SettingsBase.GetPropertyValueByName(String propertyName)
   at System.Configuration.SettingsBase.get_Item(String propertyName)
   at System.Configuration.ApplicationSettingsBase.GetPropertyValue(String propertyName)
   at System.Configuration.ApplicationSettingsBase.get_Item(String propertyName)
   at Client.Properties.Settings.get_SomeConfigSetting()
   at ...
Run Code Online (Sandbox Code Playgroud)

通过调试和日志消息,我确定永远不会调用类的初始化方法,因此从不实例化类.换句话说,上述异常背后似乎没有隐藏的初始化错误.

另一个可能重要的部分:客户端当前在.NET 2.0上运行,并且在可预见的未来没有计划进行升级.

更新2

我开始根据@jwddixon的回答调查AppDomain.首先,我想检查Client.dll是否真的在与调用者EXE不同的应用程序域中结束.所以我在当前app域中列出了程序集,并且看到Client实际上就在那里.但令我惊讶的是,我注意到列表中实际上有两个名为Client的程序集- EXE和DLL具有相同的程序集名称,但是版本不同(EXE为4.0.0.0,目前DLL为4.0.1352.0) ).到目前为止,我还没有完全意识到这一点,这可能很重要.接下来我会尝试更改EXE程序集名称...

更新3

......这实际上解决了这个问题!Aaargh ......对于那些为谁知道原因而发明这种扭曲计划的未知前辈,我现在有非常不满意的想法......但是对你们所有人提出的问题和想法最终导致解决方案感到荣幸!

DIX*_*WDD 1

我还没有尝试过这个,但是像这样的东西怎么样:

AppDomainSetup setup = AppDomain.CurrentDomain.SetupInformation;
AppDomain domain = AppDomain.CreateDomain("myAppDomain", null, setup)
setup.ApplicationBase = file;

Assembly assy = domain.Load(AssemblyName.GetAssemblyName(
AppDomain.CurrentDomain.BaseDirectory +
 "client.dll"));

object frm = assy.CreateInstance("Client.Forms.MainForm");
Application.Run((Form)frm);
Run Code Online (Sandbox Code Playgroud)