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

本文关键字:程序 反射 用于 设置 程序集 何使 动态 加载 集中 | 更新日期: 2023-09-27 18:01:53

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

public sealed class MySettings : SettingsProvider
{
    ...
}
[SettingsProvider(typeof(MySettings))]
internal sealed partial class Settings {}

然而,现在我遇到了另一个问题。

我们的客户端应用程序包括一个自动更新功能,它的实现使得客户端的大部分-包括上面的类-被构建到一个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);
这样做的不幸后果是框架无法在动态加载的程序集中找到我的自定义设置提供程序类。我试图使用LoadFrom而不是上面的LoadFile,但它没有帮助。到目前为止,我发现的唯一可行的解决方案是在加载器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 ...

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

还有一个潜在的重要信息:客户端目前运行在。net 2.0上,在可预见的未来没有升级的计划。

更新2

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

3

更新

…这实际上解决了问题!了……对于那些不知名的前辈们,谁知道他们为什么发明了这个扭曲的方案,我此刻有很不愉快的想法……但是感谢你们所有人提出的问题和想法,这些问题和想法最终导致了解决方案!

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

我还没有尝试过,但是如何像这样的东西:

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);