Los metadatos de MEF aseguran que la clase implementa la interfaz indicada en el atributo de metadatos

Hola, tengo un contenedor MEF que detecta atributos de metadatos y me gustaría ampliar esto y permitir que las clases implementen interfaces adicionales (en el ejemplo a continuación, donde quiero implementar una interfaz adicional IPluginSettings).

El identificador GUID del módulo es fundamental ya que se reconcilia con un ID de módulo en mi aplicación de base de datos, si consulto el contenedor MEF para mis interfaces importadas, puedo recorrerlas:

foreach (Lazy<T,IPluginMetadata> moduleInAssembly in m_Container.GetExports<T, IPluginMetadata>();)
{
  T value = moduleInAssembly.Value; // instantiate an object of type T to test for implementations of other interfaces...
  if (value is IPluginSettings)
  {
      // this module also contains an interface for settings!
  }
  Guid moduleInAssemblyId = Guid.Parse(moduleInAssembly.Metadata.PluginID);
}

Tengo algunas preguntas:

1) En el escenario anterior, tengo que instanciar la clase para probar si implementa una interfaz específica, ¿hay una mejor manera de hacerlo con metadatos y mejorar PluginExportAttribute para aceptar una lista de tipos de interfaz secundarios?

2) ¿Cómo puedo decirle al contenedor MEF que importe tipos que solo tienen el atributo PluginExportAttribute?

3) O en lugar de tener cada interfaz de complemento flexible/libre para declarar su propia interfaz, ¿sería mejor que los complementos implementaran una interfaz de complemento conocida que contuviera una fábrica para instanciar la interfaz de complemento específica? (Ejemplo de lo que estoy preguntando está en la parte inferior del código - última sección)

4) Gracias a una respuesta propuesta, estoy usando un código estructurado según el fragmento de la pregunta 4 a continuación y ¡funciona! Por curiosidad, ¿hay alguna forma de fusionar múltiples atributos de exportación separados en PluginExportAttribute, tal vez en un parámetro de constructor para tomar una lista de tipos adicionales para registrar?

Gracias,

Chris

public interface IPluginMetadata
{
    string PluginID { get; }
}

[MetadataAttribute]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class PluginExportAttribute : ExportAttribute, IPluginMetadata
{
    public PluginExportAttribute(Type t, string guid)
        : base(t)
    {
        PluginID = guid.ToUpper();
    }

    public string PluginID { get; set; }
}


[PluginExport(typeof(IAccountsPlugin),"BE112EA1-1AA1-4B92-934A-9EA8B90D622C")]
public class BillingModule : IAccountsPlugin, IPluginSettings
{
   // my class contents
}

o sería mejor hacer algo como esto...?

// or would i be better of by implementing a plugin base, and getting instances of the plugin via a secondary factory?
public interface IWellKnownPluginBase
{
    Guid PluginID { get; }
    Version Version { get; }
    IPluginSettings Settings { get; }
    Type GetPluginInterfaceType { get; }
    object PluginInterfaceFactory();
}

public interface IMyPlugin
{
    void DoSomethingCool();
}

[Export(typeof(IWellKnownPluginBase))] 
public class MyPluginWrapper : IWellKnownPluginBase
{
    private readonly string ID = "BE112EA1-1AA1-4B92-934A-9EA8B90D622C";

    Guid PluginID { get { return Guid.Parse(ID); } }
    Version Version { get {return new Version(1,0,0); } }
    IPluginSettings Settings { get { return new SomethingThatImplementsIPluginSettings(); }
    Type GetPluginInterfaceType { get { return gettype(IMyPlugin); }
    object PluginInterfaceFactory() { return new MyPlugin(); }

    class MyPlugin : IMyPlugin
    {
        void DoSomethingCool() {}
    }
}

Pregunta 4: ¿Se puede reescribir PluginExport para registrar múltiples interfaces con una lista de interfaces en el constructor?

[Export(typeof(IPluginSettings))]
[PluginExport(typeof(IAccountsPlugin),"BE112EA‌​1-1AA1-4B92-934A-9EA8B90D622C")]
public MyModule class : IModule, IPluginSettings
{
} 

preguntado el 22 de mayo de 12 a las 12:05

1 Respuestas

En el escenario anterior, tengo que crear una instancia de la clase para probar si implementa una interfaz específica, ¿hay una mejor manera de hacerlo con metadatos y mejorar PluginExportAttribute para aceptar una lista de tipos de interfaz secundaria?

Normalmente haría esto al tener múltiples exportaciones:

[Export(typeof(IPluginSettings))]
[Export(typeof(IModule))]
public class MyModule : IModule, IPluginSettings
{
}

En lugar de verificar si hay una interfaz presente, el consumidor (es decir, el importador o, en su caso, la persona que llama de GetExports) puede solicitar la interfaz correcta.

contestado el 22 de mayo de 12 a las 15:05

Hola Wim, gracias, eso funciona. ¿Hay alguna manera de que esto se pueda fusionar en un solo atributo? Modifiqué mi lista de preguntas original y agregué una última pregunta 4. Aparte de eso, creo que eso está resuelto. - Morleyc

@g18c: que yo sepa, no. Un atributo de exportación exporta un contrato. - Wim Coenen

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.