2012-08-14 14 views
7

Ich versuche, Plugins zur Laufzeit zu laden und auf ihre Konfigurationsdateien zuzugreifen. Die Konfigurationsabschnitte in ihren Konfigurationsdateien sind Klassen zugeordnet, die von ConfigurationElementCollection, ConfigurationElement und ConfigurationSection abgeleitet sind. Die Plugins und ihre Konfigurationsdateien befinden sich in einem Unterordner namens "Plugins".MEF-Plugins mit eigenen Konfigurationsdateien?

Das Problem ist, dass ich nicht scheinen kann, laden Sie die Plugin-Konfigurationsdaten und deserialize es in ihren jeweiligen Klassen korrekt. Hier

ist ein Beispiel für ein Plugin Config für das Plugin 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="[email protected]" 
        recipients="[email protected], [email protected]" 
        subject = "Error occurred" 
        body = "An error was detected" 
      /> 
    </EmailSettings> 
    </EmailConfigurationSection> 
</configuration> 

Ich lade diese mit diesem 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; 
     } 
    } 

Diese im Fehler führt:

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. 

Ich habe dies oben in der Konfigurationsdatei hinzugefügt:

<runtime> 
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> 
    <probing privatePath="Plugins"/> 
    </assemblyBinding> 
</runtime> 

So wird die DLL gefunden, aber es wirft keinen nicht auf die richtige Klasse, wenn ich versuche, es abzurufen:

EmailConfigurationSection defaults = CurrentConfiguration.Sections["EmailConfigurationSection"] as EmailConfigurationSection; 

Es gibt immer null. Ich weiß, dass es an der richtigen Stelle und Konfigurationsdatei suchen, weil ich die XML mit diesem Code abrufen kann:

var section = CurrentConfiguration.Sections["EmailConfigurationSection"]; 
string configXml = section.SectionInformation.GetRawXml(); 

Allerdings, wenn ich versuche, es mit diesem Code deserialisieren:

var serializer = new XmlSerializer(typeof(EmailConfigurationSection)); 
object result; 

EmailConfigurationSection defaults; 
using (TextReader reader = new StringReader(configXml)) 
{ 
    defaults = (EmailConfigurationSection)serializer.Deserialize(reader); 
} 

... ich erhalte eine Ausnahme:

There was an error reflecting type 'Foo.Plugins.EmailConfigurationSection'. 

Dies ist der Inhalt der Innerexception:

You must implement a default accessor on System.Configuration.ConfigurationLockCollection because it inherits from ICollection. 

Ich gehe davon aus es mit Bezug auf die Klasse EmailConfigElementCollection, aber dann wird die Meldung nicht sinnvoll, da diese Klasse eine Standard Accessor hat:

public EmailConfigElement this[int index] 
    { 
     get 
     { 
      return (EmailConfigElement)BaseGet(index); 
     } 
     set 
     { 
      if (BaseGet(index) != null) 
      { 
       BaseRemoveAt(index); 
      } 
      BaseAdd(index, value); 
     } 
    } 

ich diesen Code erfolgreich in anderen Projekten verwendet habe (auch mit separate DLLs/configs), aber dies ist das erste Mal, dass ich versuche, es mit MEF zu verwenden. Weiß jemand, was das Problem ist, oder eine geeignete Problemumgehung? .NET 4.5

+0

Ich habe irgendwo gelesen, dass man einfach die ExecutingAssebly verwenden können.Speicherort in Ihrer OpenExeConfiguration – Luke

+0

mögliches Duplikat von [Benutzerdefinierte Konfigurationsabschnitte in MEF-exportierenden Baugruppen] (http://stackoverflow.com/questions/4845801/custom-configuration-sections-in-mef-exporting-assemblies) –

+0

Dies ist nicht so viel ein Duplikat, aber eine direkte Kopie von http://social.msdn.microsoft.com/Forums/en-US/16df81ea-270b-47e2-bd30-877e0e32c88c/mef-plugins-with-their-own-configuration-files –

Antwort

5

Ich reparierte diese mit der folgenden Modifikation

Ich verwende:

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

Ich habe diese von dieser Frage: Custom configuration sections in MEF exporting assemblies. Ich hatte es tatsächlich vorher ohne Erfolg versucht.

Der Trick dabei war, dass ich die Laufzeit-Tag an der Unterseite der XML-Konfiguration zu bewegen hatte:

<?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

Sie brauchen nicht einmal Laufzeitabschnitt in der Konfigurationsdatei. –

Verwandte Themen