2010-09-02 26 views
5

我一直在試圖找出這幾天,沒有運氣。ImportMany與元數據無法導入

我試圖使用[ImportMany]從一個完整的DLL目錄中導入類型爲IEditorSystem的導出,該導入具有IEditorSystemMetadata類型的自定義元字體。我想首先獲取元數據,並將其推送到某些文本框等,以便用戶可以選擇使用哪個EditorSystem,並在選擇時加載該系統...

我一直在關注以下示例盡我所能,這是迄今爲止我所擁有的。

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

這是它應該導入:

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

和啓動:

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

我可以在Catalog.Parts同時看到MyEditorSystem並且具有視圖模型ImportMany,但EditorSystemList永遠不會被填充。我沒有得到組合錯誤。

我認爲它可能有一些做的懶惰<>,所以我嘗試

public ObservableCollection<IEditorSystem> EditorSystemList 

沒有任何運氣。

我能想到的唯一複雜因素是我使用的是使用MEFedMVVM的Cinch,它也使用MEF。我不想認爲它干涉,但我不確定。

我想我做錯了,任何人都可以理解這一點嗎?

更新:

實現新的IComposer,與正是你所需要的目錄。

雖然ImportMany仍然失敗,但只有當我嘗試導入元數據時纔會這樣。元數據僅僅是一對字符串,並且就我能夠確定的而言,遵循這些示例。

最終找到原因:如前所述,IEditorSystem的實現位於獨立的DLL中。 但是,任何新版本的dll都不會複製到主項目的輸出子目錄中。 我已經手動複製了第一個,並忘記將後生成的副本添加到dll項目。 哦,學到了一堆關於MEF的東西,所以不能完全浪費天:)

回答

1

沒有看到你的代碼,我相信所有你需要改變的是

public ObservableCollection<Lazy<IEditorSystem, IEditorSystemMetadata>> EditorSystemList 

應該

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

這裏有一個例子:

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

我將其更改爲IEnumerable,但導入從未似乎完成,EditorSystemList保持在[0] ... – Kage 2010-09-03 03:48:55

+0

您是否嘗試運行上面的確切代碼?你應該能夠創建一個控制檯應用程序來測試。 – JoshVarga 2010-09-03 15:06:05

+0

是的,控制檯版本可以工作,但它看起來可能是由於MEFedMVVM搞砸了,會更新 – Kage 2010-09-04 09:28:42

0

也許我解決方案也解決了你的問題。

我一直在努力嘗試發現問題。

然後我得到了以下解決方案:

元數據接口應當只包含一個相同類型的屬性:如果你把int兩個屬性,例如

intboolstring等, ImportMany<Lazy<t,m>>將不起作用,它將始終返回0.

對於接口的每個屬性,必須將ExportMetadata屬性放在導出的類上。

例如,

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

也許我的解決方案解決你的問題了。

我一直在努力嘗試發現問題。

然後我得到了以下解決方案:

元數據接口應當只包含一個相同類型的屬性:

整型,布爾,字符串,等等。如果你把Int的兩個屬性,例如, ImportMany>將不起作用,它將始終返回0.

對於接口的每個屬性,必須將ExportMetadata屬性置於導出的類上。

例如,

公共接口IMyExportMetadata { INT一個{獲得;} 串B {得到; } 布爾13 C {獲得;} }

[導出(typeof運算(IMyInterface的)) [ExportMetadata( 「一」,0)] [ExportMetadata( 「B」, 「串」)] [ExportMetadata( 「C」,真)] 公共類myExportedClass:IMyInterface的 { }

與多個布爾工作,例如,你必須創建一個自定義導出屬性實現元數據接口是這樣的:

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