我正在尝试在运行时加载插件并访问它们的配置文件。它们配置文件中的配置部分映射到从ConfigurationElementCollection、ConfigurationElement和ConfigurationSection派生的类。这些插件及其配置文件位于名为“Plugins”的子文件夹中。
问题在于我似乎无法正确地加载插件配置数据并将其反序列化为它们各自的类。
以下是EmailPlugin.dll的插件配置示例:
我使用以下代码加载它:
这会导致错误:
然而,当我尝试使用以下代码进行反序列化时:
我猜它指的是EmailConfigElementCollection类,但是这个消息没有意义,因为这个类确实有一个默认访问器:
问题在于我似乎无法正确地加载插件配置数据并将其反序列化为它们各自的类。
以下是EmailPlugin.dll的插件配置示例:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="EmailConfigurationSection" type="Foo.Plugins.EmailConfigurationSection, EmailPlugin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" allowDefinition="Everywhere" allowExeDefinition="MachineToApplication" restartOnExternalChanges="true"/>
</configSections>
<EmailConfigurationSection server="192.168.0.10">
<EmailSettings>
<add keyword="ERROR"
sender="error@error.com"
recipients="foo@bar.com, wiki@waki.com"
subject = "Error occurred"
body = "An error was detected"
/>
</EmailSettings>
</EmailConfigurationSection>
</configuration>
我使用以下代码加载它:
private static System.Configuration.Configuration config = null;
public static System.Configuration.Configuration CurrentConfiguration
{
get
{
if (config == null)
{
Assembly assembly = Assembly.GetAssembly(typeof(EmailPlugin));
string directory = Path.GetDirectoryName(assembly.CodeBase);
string filename = Path.GetFileName(assembly.CodeBase);
string assemblyPath = Path.Combine(directory, filename);
config = ConfigurationManager.OpenExeConfiguration(new Uri(assemblyPath).LocalPath);
}
return config;
}
}
这会导致错误:
这会导致错误:
An error occurred creating the configuration section handler for EmailConfigurationSection: Could not load file or assembly 'EmailPlugin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.
我把以下内容添加到配置文件的顶部:
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="Plugins"/>
</assemblyBinding>
</runtime>
所以 DLL 被找到了,但在我尝试检索它时没有被转换为适当的类:
EmailConfigurationSection defaults = CurrentConfiguration.Sections["EmailConfigurationSection"] as EmailConfigurationSection;
它总是返回 null。我知道它正在查看正确的位置和配置文件,因为我可以使用以下代码检索 XML:
var section = CurrentConfiguration.Sections["EmailConfigurationSection"];
string configXml = section.SectionInformation.GetRawXml();
然而,当我尝试使用以下代码进行反序列化时:
var serializer = new XmlSerializer(typeof(EmailConfigurationSection));
object result;
EmailConfigurationSection defaults;
using (TextReader reader = new StringReader(configXml))
{
defaults = (EmailConfigurationSection)serializer.Deserialize(reader);
}
当我运行程序时,出现了一个异常:
There was an error reflecting type 'Foo.Plugins.EmailConfigurationSection'.
以下是InnerException的内容:
You must implement a default accessor on System.Configuration.ConfigurationLockCollection because it inherits from ICollection.
我猜它指的是EmailConfigElementCollection类,但是这个消息没有意义,因为这个类确实有一个默认访问器:
public EmailConfigElement this[int index]
{
get
{
return (EmailConfigElement)BaseGet(index);
}
set
{
if (BaseGet(index) != null)
{
BaseRemoveAt(index);
}
BaseAdd(index, value);
}
}
我以前在其他项目中成功地使用过这段代码(甚至使用了单独的DLLs/configs),但这是我第一次尝试在MEF中使用它。有人知道问题出在哪里,或者有合适的解决方法吗?
我正在使用.NET 4.5