2010-09-02 14 views
5

He estado tratando de resolver esto por unos días, sin suerte.ImportMany con Metadata sin importar

Estoy tratando de usar [ImportMany] para importar desde un directorio lleno de DLL con exportaciones de tipo IEditorSystem, que tienen metadatos personalizados de tipo IEditorSystemMetadata. Me gustaría obtener los metadatos primero, y enviarlos a algunos cuadros de texto, etc. para que el usuario pueda elegir qué sistema Editor usar, y cuando se selecciona, cargar ese sistema ...

He estado siguiendo ejemplos como los mejores como puedo, esto es lo que tengo hasta ahora.

[ImportMany] 
public ObservableCollection<Lazy<IEditorSystem, IEditorSystemMetadata>> EditorSystemList 

Esto es lo que debe importar:

[Export(typeof(IEditorSystem))] 
    [SignalSystemData("Very Very Long Name", "Short Name")] 
    public class MyEditorSystem: IEditorSystem 
    { 
     public MyEditorSystem() 
     { 
     } 
    } 

y la puesta en marcha:

AggregateCatalog Catalog = new AggregateCatalog(
       new DirectoryCatalog(@".\EditorSystems"), 
       new AssemblyCatalog(Assembly.GetExecutingAssembly())); 
      CompositionContainer Container = new CompositionContainer(Catalog); 
      Container.ComposeParts(this); 

que puede ver en la Catalog.Parts tanto el MyEditorSystem y el modelo de vista que tiene el ImportMany, pero EditorSystemList nunca se llena. No obtengo errores de composición.

pensé que podría tener algo que ver con el Lazy <>, así que traté

public ObservableCollection<IEditorSystem> EditorSystemList 

No hubo suerte tampoco.

La única complicación que puedo pensar es que estoy usando Cinch, que usa MEFedMVVM, que también usa MEF. Yo no creo que interfiere, pero no estoy muy seguro.

Me imagino que lo estoy haciendo mal, ¿alguien puede darle sentido a esto?

Actualización:

implementar un nuevo IComposer, con exactamente el catálogo que necesita.

ImportMany sigue fallando, pero solo cuando trato de importar metadatos con él. Los metadatos son solo un par de cadenas y, en la medida en que puedo determinar, sigue los ejemplos.

FINALMENTE encontró la causa: las implementaciones de IEditorSystem están en una DLL separada, como se señaló anteriormente. Sin embargo, las compilaciones nuevas de la DLL no se copian en el subdirectorio de salida del proyecto principal. Copié el primero manualmente y olvidé agregar una copia posterior a la compilación en el proyecto dll. Bueno, aprendido un montón de cosas sobre el MEF, días, así que no completamente desperdiciados :)

Respuesta

1

Sin ver su código, creo que todo lo que tiene que cambiar es

public ObservableCollection<Lazy<IEditorSystem, IEditorSystemMetadata>> EditorSystemList 

debería ser

public IEnumerable<Lazy<IEditorSystem, IEditorSystemMetadata>> EditorSystemList; 

Este es un ejemplo:

class Program 
{ 
    static void Main(string[] args) 
    { 
     var c = new Class1(); 
     var v = c.EditorSystemList; 
     foreach (var lazy in v) 
     { 
      if (lazy.Metadata.LongName == "Very Very Long Name") 
      { 
       var v2 = lazy.Value; 
       // v2 is the instance of MyEditorSystem 
      } 
     } 
    } 
} 

public class Class1 
{ 
    [ImportMany] 
    public IEnumerable<Lazy<IEditorSystem, IEditorSystemMetadata>> EditorSystemList; 

    public Class1() 
    { 
     var catalog = new AggregateCatalog(
      new AssemblyCatalog(Assembly.GetExecutingAssembly())); 
     var container = new CompositionContainer(catalog); 
     container.ComposeParts(this); 
    } 
} 

[Export(typeof(IEditorSystem))] 
[SignalSystemData("Very Very Long Name", "Short Name")] 
public class MyEditorSystem : IEditorSystem { } 

public interface IEditorSystem { } 

[MetadataAttribute] 
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] 
public class SignalSystemDataAttribute : ExportAttribute 
{ 
    public SignalSystemDataAttribute(string longName, string shortName) 
     : base(typeof(IEditorSystem)) 
    { 
     LongName = longName; 
     ShortName = shortName; 
    } 
    public string LongName { get; set; } 
    public string ShortName { get; set; } 
} 

public interface IEditorSystemMetadata 
{ 
    string LongName { get; } 
    string ShortName { get; } 
} 
+0

Lo cambié a IEnumerable, pero la importación parece que nunca termina, EditorSystemList permanece en [0] ... – Kage

+0

¿Intentó ejecutar el código exacto desde arriba? deberías poder crear una aplicación de consola para probar eso. – JoshVarga

+0

Sí, la versión de la consola funciona, pero parece que podría deberse a que MEFedMVVM ha estropeado las cosas, se actualizará – Kage

0

Tal vez mi la solución también resuelve tu problema.

Estaba trabajando duro para descubrir el problema.

entonces tiene la siguiente solución:

interfaz de metadatos deben contener sólo una propiedad del mismo tipo:

int, bool, string, etc. Si pones dos propiedades de int, por ejemplo, el ImportMany<Lazy<t,m>> no funcionará y siempre devolverá 0.

para cada propiedad de la interfaz, debe poner el atributo ExportMetadata en la clase exportada.

por ejemplo,

public interface IMyExportMetadata 
{ 
    int a {get;} 
    string b {get;} 
    bool c {get;} 
} 

[Export(typeof(IMyInterface)) 
[ExportMetadata("a", 0)] 
[ExportMetadata("b", "string")] 
[ExportMetadata("c", true)] 
public class myExportedClass: IMyInterface 
{ 
} 
1

Tal vez mi solución resuelve su problema también.

Estaba trabajando duro para descubrir el problema.

entonces tiene la siguiente solución:

interfaz de metadatos deben contener sólo una propiedad del mismo tipo:

int, bool, hilo, etc. Si pones dos propiedades de Int, por ejemplo, ImportMany> no funcionará y siempre devolverá 0.

para cada propiedad de la interfaz, debe colocar el atributo ExportMetadata en la clase exportada.

por ejemplo,

interfaz pública IMyExportMetadata {int a {get;} cadena b {get; } bool c {get;} }

[Exportar (typeof (IMyInterface)) [ExportMetadata ("a", 0)] [ExportMetadata ("b", "cadena")] [ExportMetadata ("c", true)] myExportedClass clase pública: IMyInterface { }

para trabajar con múltiples booleanos, por ejemplo, debe crear un atributo de exportación personalizada que implementa la interfaz de metadatos como esto:

[MetadataAttribute] 
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)] 
public class ExportUserPartAttribute : ExportAttribute, IUserPartMetadata 
{ 
    #region Implementation of IUserPartMetadata 

    public int TipoPart { get; set; } 
    public string Regiao { get; set; } 
    public bool IsLogin { get; set; } 
    public bool IsMenu { get; set; } 
    public bool IsHome { get; set; } 
    public bool IsListagem { get; set; } 
    public bool IsFormulario { get; set; } 

    #endregion 

    public ExportUserPartAttribute() 
     : base(typeof(IUserPart)) 
    { 

    } 

    /* 
    public ExportUserPartAttribute(int tipoPart, string regiao) 
     : base(typeof(IUserPart)) 
    { 
     this.TipoPart = tipoPart; 
     this.Regiao = regiao; 
    } 
    */ 
} 
Cuestiones relacionadas