加载dll

时间:2019-04-19 18:50:43

标签: c# .net dll configurationmanager configurationsection

我正在编写一个可以使用插件扩展的应用程序(出售这些插件需要支付额外的许可费用)。其中一些插件需要特定于插件的配置,该配置可由用户更新,因此该配置不是固定的。

现在我已经向此类插件添加了配置文件,但是当插件加载ConfigurationSection(映射到类)时,它引发了一个异常,即无法加载定义了ConfigurationSection的文件或程序集。与定义插件代码的位置完全相同(即,插件已加载)。

在我的主应用程序中,我使用以下代码在插件程序集中找到插件类并将其实例化(将程序集加载到AppDomain中(为了便于阅读,我省略了所有错误检查):

// Load the assembly
AssemblyName assemblyName = new AssemblyName();
assemblyName.CodeBase = assemblyPath;
Assembly assembly = Assembly.Load(assemblyName);

// Load the types from the assembly
Type[] types = assembly.GetTypes();
foreach (Type type in types)
{
    if (null != type.GetInterface(typeof(IPlugin).FullName))
    {
        IPlugin plugin = Activator.CreateInstance(type) as IPlugin;
        // ... do something with the plugin
    }
}

现在,我具有在其中实现了插件的程序集MyPlugin.dll。在这个项目中,我有一个MyPlugin.dll.config文件,该文件在构建插件时会复制到输出文件夹中。 MyPlugin.dll.config具有以下内容:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <configSections>
        <section allowExeDefinition="MachineToLocalUser" name="mysettings" restartOnExternalChanges="false" requirePermission="false" type="Plugin.MySettings, MyPlugin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1234567890abcdef" />
    </configSections>
</configuration>

还在插件中,我定义了类Plugin.MySettings:

namespace Plugin
{
    public class MySettings : ConfigurationSection
    {
        public MySettings() : base() {}

        [ConfigurationProperty("someproperty", DefaultValue = null, IsRequired = false]
        public string SomeProperty
        {
            get { return (string)this["someproperty"]; }
            set { this["someproperty"] = value; }
        }
    }
}

然后,我尝试按以下方式加载dll配置文件(在本示例中,我仅使用特殊应用程序数据文件夹的子文件夹,但是在实际应用程序中,我对这些配置文件使用更深的层次结构,但这并不重要):

ExeConfigurationFileMap configurationMap = new ExeConfigurationFileMap();
configurationMap.ExeConfigFilename = assembly.Location + ".config";
configurationMap.LocalUserConfigFilename = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
                                                        "Plugins",
                                                        "MyPlugin.config");
configurationMap.RoamingUserConfigFilename = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
                                                          "Plugins",
                                                          "MyPlugin.config");
Configuration config = ConfigurationManager.OpenMappedExeConfiguration(configurationMap, ConfigurationUserLevel.PerUserRoamingAndLocal);
MySettings settings = config.GetSection("mysettings") as MySettings;

但是,当我这样做时,打开配置文件(对GetSection的调用)会引发异常:

An error occurred creating the configuration section handler for mysettings: Could not load file or assembly 'MyPlugin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1234567890abcdef' or one of its dependencies. The system cannot find the file specified. (<outputpath>\MyPlugin.dll.config line 4)

现在我已经尝试了以下操作:

1。在配置文件中添加一个空的mysettings标记:

我在配置文件中添加了一个空的mysettings标记,使其变为:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <configSections>
        <section allowExeDefinition="MachineToLocalUser" name="mysettings" restartOnExternalChanges="false" requirePermission="false" type="Plugin.MySettings, MyPlugin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1234567890abcdef" />
    </configSections>
    <mysettings />
</configuration>

这给出了与最初抛出的异常完全相同的异常。

2。删除configSections标记

我已经删除了配置文件中的configSections标记,使得它像这样:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <section allowExeDefinition="MachineToLocalUser" name="mysettings" restartOnExternalChanges="false" requirePermission="false" type="Plugin.MySettings, MyPlugin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1234567890abcdef" />
</configuration>

这没有导致异常,而是导致设置变量为null。仔细检查发现,在这种情况下,mysettings ConfigurationSection的类型为System.Configuration.DefaultSection。

我必须忽略某些东西,但是程序集MyPlugin已加载(因为从插件程序集内执行了用于加载配置文件的代码。请注意,当用户数据文件夹中没有配置文件时,将执行该代码,仅输出文件夹中dll文件旁边的给定配置文件。

我已经看过互联网和堆栈溢出上的其他文章,但是它们没有使用自定义ConfigurationSections,而是直接在配置文件中的appSettings中使用键值对,而且这些配置似乎是固定的(即,由用户更新)。这些不匹配的问题的示例是:C# DLL config fileEquivalent to 'app.config' for a library (DLL)。 但是,我想使用一个类作为ConfigSection,因此可以更轻松地在需要的插件代码中提取属性。

有什么办法可以使它正常工作?

更新

我一直在进一步研究这个问题。问题是ConfigurationManager试图从与应用程序本身所在的文件夹相同的文件夹中加载插件程序集。但是,插件存储在应用程序的子文件夹中。

针对我的具体情况的解决方案(这就是为什么我没有创建答案的原因,因为最初的问题并不是真正的问题)是在应用程序配置中添加probing element指向文件夹中插件是。这样,配置子系统也可以找到插件程序集,一切都很好。

问候, 马塞尔

0 个答案:

没有答案