2012-08-14 56 views
7

我想在運行時加載插件並訪問它們的配置文件。配置文件中的配置節映射到派生自ConfigurationElementCollection,ConfigurationElement和ConfigurationSection的類。插件及其配置文件位於稱爲「插件」的子文件夾中。MEF插件與他們自己的配置文件?

問題是我似乎無法加載插件配置數據並將其反序列化到它們各自的類中。

這裏是插件EmailPlugin.dll插件配置的一個示例:

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. 

<?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="[email protected]" 
        recipients="[email protected], [email protected]i.com" 
        subject = "Error occurred" 
        body = "An error was detected" 
      /> 
    </EmailSettings> 
    </EmailConfigurationSection> 
</configuration> 

我此使用此代碼加載

我將此添加到配置文件的頂部:

<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

+0

我讀的地方,你可以簡單地使用ExecutingAssebly。您的OpenExeConfiguration中的位置 – Luke 2012-12-12 14:43:30

+0

可能重複[MEF導出程序集中的自定義配置節](http://stackoverflow.com/questions/4845801/custom-configuration-sections-in-mef-exporting-assemblies) – 2013-07-08 21:09:52

+0

這不是那麼多一個副本,但直接副本http://social.msdn.microsoft.com/Forums/en-US/16df81ea-270b-47e2-bd30-877e0e32c88c/mef-plugins-with-their-own-configuration-files – 2013-09-25 19:44:13

回答

5

我解決了這個問題作以下修改:

public static System.Configuration.Configuration CurrentConfiguration 
{ 
    get 
    { 
     if (config == null) 
     { 
      // Added the next bit 
      AppDomain.CurrentDomain.AssemblyResolve += (o, args) => 
      { 
       var loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies(); 
       return loadedAssemblies.Where(asm => asm.FullName == args.Name) 
              .FirstOrDefault(); 
      }; 

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

我得到這個從這個問題: Custom configuration sections in MEF exporting assemblies。我實際上早先嚐試過沒有成功。

訣竅是,我不得不運行標籤移到XML配置的底部:

<?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="255.255.255.1"> 
    <EmailSettings> 
     <clear /> 
     <add keyword="FOO" 
        sender="[email protected]" 
        recipients="[email protected]" 
        subject = "Foo occurred" 
        body = "Hello" 
      /> 
    </EmailSettings> 
    </EmailConfigurationSection> 
    <runtime> 
     <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> 
     <probing privatePath="Plugins"/> 
     </assemblyBinding> 
    </runtime> 
</configuration> 
+0

你甚至不需要配置文件中的運行時段。 – 2015-05-25 03:41:58