2010-09-02 14 views
5

J'ai essayé de comprendre ceci pendant quelques jours maintenant, sans chance. J'essaie d'utiliser le [ImportMany] pour importer à partir d'un répertoire plein de DLL avec des exportations de type IEditorSystem, qui ont métadonnées personnalisées de type IEditorSystemMetadata. Je voudrais obtenir les métadonnées en premier, et le pousser vers des zones de texte, etc afin que l'utilisateur puisse choisir le système d'édition à utiliser, et lorsqu'il est sélectionné, charger ce système ...ImportMany avec des métadonnées ne pas importer

J'ai suivi les exemples comme meilleurs comme je peux, voici ce que j'ai jusqu'ici.

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

C'est ce qu'il doit être importé:

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

et la mise en service:

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

je peux voir dans les Catalog.Parts à la fois le MyEditorSystem et le viewmodel qui a la ImportMany, mais EditorSystemList n'est jamais renseigné. Je ne reçois aucune erreur de composition.

Je pensais que cela pourrait avoir quelque chose à voir avec le Lazy <>, donc j'ai essayé

public ObservableCollection<IEditorSystem> EditorSystemList 

Pas de chance non plus.

La seule complication que je peux penser est que j'utilise Cinch, qui utilise MEFedMVVM, qui utilise également MEF. Je ne pense pas que ça interfère, mais je ne suis pas vraiment sûr.

Je me dis que je me trompe, quelqu'un peut-il donner un sens à cela?

Mise à jour:

Mettre en oeuvre une nouvelle IComposer, avec exactement le catalogue dont vous avez besoin.

ImportMany échoue toujours, mais seulement quand j'essaye d'importer des métadonnées avec lui. Les métadonnées sont juste un couple de chaînes, et autant que je suis capable de déterminer, suit les exemples. FINALEMENT trouvé la cause: Les implémentations de IEditorSystem sont dans une DLL séparée, comme indiqué précédemment. Cependant, les nouvelles versions de la DLL ne sont pas copiées dans le sous-répertoire de sortie du projet principal. J'avais copié le premier manuellement, et j'ai oublié d'ajouter une copie de post-construction au projet dll. Eh bien, appris un tas de choses sur MEF, donc pas complètement gaspillés jours :)

Répondre

1

Sans voir votre code, je crois que tout ce que vous devez changer est

public ObservableCollection<Lazy<IEditorSystem, IEditorSystemMetadata>> EditorSystemList 

devrait être

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

Voici un exemple:

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

Je l'ai changé en IEnumerable, mais l'importation ne semble jamais se faire, EditorSystemList reste à [0] ... – Kage

+0

Avez-vous essayé d'exécuter le code exact d'en haut? vous devriez être capable de créer une application console pour tester cela. – JoshVarga

+0

Oui, la version de la console fonctionne, mais il semble que cela soit dû au fait que MEFedMVVM ait brouillé les choses. – Kage

0

Peut-être que mon solution résout votre problème aussi.Je travaillais dur en essayant de découvrir le problème.

puis je me suis la solution suivante:

Interface Les métadonnées doivent contenir une seule propriété du même type:

int, bool, string, etc. Si vous mettez deux propriétés de int, par exemple, le ImportMany<Lazy<t,m>> ne fonctionnera pas et il renverra toujours 0.

pour chaque propriété de l'interface, vous devez mettre l'attribut ExportMetadata à la classe exportée à.

par exemple,

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

Peut-être que ma solution permet de résoudre votre problème aussi. Je travaillais dur en essayant de découvrir le problème.

puis je me suis la solution suivante:

Interface Les métadonnées doivent contenir une seule propriété du même type:

int, bool, string, etc. Si vous mettez deux propriétés de Int, par exemple, le ImportMany> ne fonctionnera pas et il retournera toujours 0.

Pour chaque propriété de l'interface, vous devez mettre l'attribut ExportMetadata de la classe exportée à.

par exemple,

interface publique IMyExportMetadata {int un {get;} string b {get; } bool c {get;} }

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

de travailler avec plusieurs booléens, par exemple, vous devez créer un attribut d'exportation personnalisé qui implémente l'interface de métadonnées comme ceci:

[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; 
    } 
    */ 
} 
Questions connexes