title: MEF plugins with their own configuration files?
body: <p>I'm trying to load plugins at runtime and access their configuration files.  The configuration sections in their config files are mapped to classes derived from ConfigurationElementCollection, ConfigurationElement and ConfigurationSection.  The plugins and their configuration files are location in a subfolder called "Plugins".</p>
  
  <p>The problem is that I can't seem to load the plugin configuration data and deserialize it into their respective classes correctly.</p>
  
  <p>Here is an example of a plugin config for the plugin EmailPlugin.dll:</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="utf-8" ?&gt;
  &lt;configuration&gt;
    &lt;configSections&gt;
      &lt;section name="EmailConfigurationSection" type="Foo.Plugins.EmailConfigurationSection, EmailPlugin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" allowDefinition="Everywhere" allowExeDefinition="MachineToApplication" restartOnExternalChanges="true"/&gt;
    &lt;/configSections&gt;
    &lt;EmailConfigurationSection server="192.168.0.10"&gt;
      &lt;EmailSettings&gt;
        &lt;add  keyword="ERROR"
                      sender="error@error.com"
                      recipients="foo@bar.com, wiki@waki.com"
                      subject = "Error occurred"
                      body = "An error was detected"
              /&gt;
      &lt;/EmailSettings&gt;
    &lt;/EmailConfigurationSection&gt;
  &lt;/configuration&gt;
  </code></pre>
  
  <p>I load this using this code:</p>
  
  <pre><code>    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;
          }
      }
  </code></pre>
  
  <p>This results in the error:</p>
  
  <pre><code>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.
  </code></pre>
  
  <p>I added this to the top of the config file:</p>
  
  <pre><code>&lt;runtime&gt;
    &lt;assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"&gt;
       &lt;probing privatePath="Plugins"/&gt;
    &lt;/assemblyBinding&gt;
  &lt;/runtime&gt;
  </code></pre>
  
  <p>So the DLL is found, but it doesn't not cast to the proper class when I try to retrieve it:</p>
  
  <pre><code>EmailConfigurationSection defaults = CurrentConfiguration.Sections["EmailConfigurationSection"] as EmailConfigurationSection;
  </code></pre>
  
  <p>It always returns null.  I know it's looking at the correct location and configuration file because I can retrieve the XML using this code:</p>
  
  <pre><code>var section = CurrentConfiguration.Sections["EmailConfigurationSection"];
  string configXml = section.SectionInformation.GetRawXml();
  </code></pre>
  
  <p>However, when I try to deserialize it with this code:</p>
  
  <pre><code>var serializer = new XmlSerializer(typeof(EmailConfigurationSection));
  object result;
  
  EmailConfigurationSection defaults;
  using (TextReader reader = new StringReader(configXml))
  {
      defaults = (EmailConfigurationSection)serializer.Deserialize(reader);
  }
  </code></pre>
  
  <p>...  I get an exception:</p>
  
  <pre><code>There was an error reflecting type 'Foo.Plugins.EmailConfigurationSection'.
  </code></pre>
  
  <p>This is the contents of the InnerException:</p>
  
  <pre><code>You must implement a default accessor on System.Configuration.ConfigurationLockCollection because it inherits from ICollection.
  </code></pre>
  
  <p>I assume it's referring to the class EmailConfigElementCollection, but then the message does not make sense because this class does have a default accessor:</p>
  
  <pre><code>    public EmailConfigElement this[int index]
      {
          get
          {
              return (EmailConfigElement)BaseGet(index);
          }
          set
          {
              if (BaseGet(index) != null)
              {
                  BaseRemoveAt(index);
              }
              BaseAdd(index, value);
          }
      }
  </code></pre>
  
  <p>I've used this code successfully in other projects (even with separate DLLs/configs), but this is the first time I'm trying to use it with MEF.  Does anyone know what the problem is, or a suitable workaround?</p>
  
  <p>I'm using .NET 4.5</p>