2011-05-04 51 views
3

原始源代碼MEF物業百達返回null

我有我的BusinessObjects.dll文件的簡單業務對象:

namespace BusinessObjects 
{ 
    public class MyClass 
    { 
     public MyClass() 
     { 
      DateTime = DateTime.Now; 
     } 

     public DateTime DateTime { get; set; } 
    } 
} 

在我SharedUI.dll我有了這個「上下文供應商」級,我用它來舉行referece當前選定的MyClass的 - 記住這是一個simplyfied例如:)...

namespace SharedUI 
{ 
    public class AppContext 
    { 
     [Export] 
     public MyClass SelectedMyClass { get; private set; } 

     public void SetupContext(MyClass myClass) 
     { 
      SelectedMyClass = myClass; 
     } 

     public static AppContext Context 
     { 
      get 
      { 
       if (context == null) 
       { 
        context = new AppContext(); 
       } 
       return context; 
      } 
     } 

     private static AppContext context; 
    } 
} 

我MefTe st.exe有這個類:

namespace MefTest 
{ 
    public class Program 
    { 
     [Import] 
     public MyClass MyClass { get; set; } 

     private void Compose() 
     { 
      var ventSystem = new MyClass(); 
      AppContext.Context.SetupContext(ventSystem); 

      var executingAssembly = new AssemblyCatalog(Assembly.GetExecutingAssembly()); 
      var contextAssembly = new AssemblyCatalog(Assembly.LoadFile(string.Format(@"{0}\SharedUI.dll", Environment.CurrentDirectory))); 
      var catalog = new AggregateCatalog(executingAssembly, contextAssembly); 

      var container = new CompositionContainer(catalog); 

      container.ComposeParts(this); 
     } 

     private void Run() 
     { 
      Compose(); 

      // MyClass is always null in the next line? 
      Console.WriteLine(MyClass.DateTime.ToString()); 

      Console.ReadKey(); 
     } 

     private static void Main(string[] args) 
     { 
      var p = new Program(); 
      p.Run(); 
     } 
    } 
} 

我是一個菜鳥MEF所以請多多包涵:)

更新的源代碼與丹尼爾·普萊斯特德

MyClass的根源的建議是相同的...

SharedUI.dll現在看起來是這樣的:

namespace SharedUI 
{ 
    [Export] 
    public class AppContext 
    { 
     [Export(typeof(MyClass))] 
     public MyClass SelectedMyClass { get; private set; } 

     public void SetupContext(MyClass myClass) 
     { 
      SelectedMyClass = myClass; 
     } 
    } 
} 

MefTest.exe現在看起來是這樣的:

namespace MefTest 
{ 
    public class Program 
    { 
     [Import] 
     public MyClass MyClass { get; set; } 

     [Import] 
     public AppContext AppContext { get; set; } 

     private void Compose() 
     { 
      var executingAssembly = new AssemblyCatalog(Assembly.GetExecutingAssembly()); 
      var contextAssembly = new AssemblyCatalog(Assembly.LoadFile(string.Format(@"{0}\SharedUI.dll", Environment.CurrentDirectory))); 
      var catalog = new AggregateCatalog(executingAssembly, contextAssembly); 

      var container = new CompositionContainer(catalog); 

      container.ComposeParts(this); 

      var myClass = new MyClass(); 
      AppContext.SetupContext(myClass); 
     } 

     private void Run() 
     { 
      Compose(); 

      // AppContext.SelectedMyClass is NOT null in the next line... which is good I guess :) 
      Console.WriteLine(AppContext.SelectedMyClass.DateTime.ToString()); 

      // MyClass is always null in the next line? 
      Console.WriteLine(MyClass.DateTime.ToString()); 

      Console.ReadKey(); 
     } 

     private static void Main(string[] args) 
     { 
      var p = new Program(); 
      p.Run(); 
     } 
    } 
} 

我在做什麼錯誤的,因爲我無法得到它的工作?

+0

您是否驗證過它將'GUI加載到AssemblyCatalog中? – 2011-05-05 08:18:49

+0

@Jonas:您是什麼意思的「GUI」?它是包含Program-class的項目,AppContext-clas s或MyClass-class ...? – kennethkryger 2011-05-05 08:41:03

+0

對不起,我混合了2個不同的SO問題:)我的意思是AppContext類。你是否證實它正在被MEF加載? – 2011-05-05 08:46:44

回答

2

當MEF需要獲得一個出口是一個類的屬性,它會創建因此MEF正在創建一個新的AppContext實例,與靜態的AppContext.Context實例不同,MEF創建的實例沒有設置SelectedMyClass屬性,這就是爲什麼您的導入結束爲空

+0

我已經更新了原來的問題與你的建議 - 但我無法得到它的工作?我在這裏錯過了什麼? – kennethkryger 2011-05-09 08:34:10

+2

@kenneth您修改過的示例有一個不同的問題。 MEF只獲取一次導出的值,並不知道它是否稍後更改。當你調用ComposeParts(this)時,它會調用MyClass導出的值。當您隨後修改該屬性時,它不會影響導出的值。 – 2011-05-18 03:06:09

0

你把你的Export屬性放在錯誤的地方。

你應該把它放在MyClass的定義,像這樣:

namespace BusinessObjects 
{ 
[Export] 
public class MyClass 
{ 
    public MyClass() 
    { 
     DateTime = DateTime.Now; 
    } 

    public DateTime DateTime { get; set; } 
} 
} 

然後使用[導入]屬性,無論你想這個類的一個實例。

備註:不能使用MEF移動一類的特定實例(不是這樣)。 MEF用於創建請求類型的實例並在指定位置注入它們。

要了解關於MEF的更多信息,請查看項目頁面CodePlex

+0

如果我正在閱讀右側的文檔[鏈接](http://msdn.microsoft.com/en-us/library/system.componentmodel.composition.exportattribute.aspx),則可以在類上使用導出屬性,方法,特性和領域...尤其是在備註部分中的下列引用引起了我的興趣:「ExportAttribute可以修飾整個類,或者類的屬性,字段或方法,如果整個類都被修飾, **「 – kennethkryger 2011-05-05 08:12:23

+1

嘗試[導出(typeof(MyClass)] public MyClass SelectedMyClass {get())public MyClass SelectedMyClass {get ; private set;} – maartenba 2011-05-05 09:33:34

+0

@maartenba:不幸的是,似乎並沒有解決它:( – kennethkryger 2011-05-05 11:04:00

1

的問題是:

[Import]  public MyClass MyClass { get; set; } 

沒有[導出] S爲MyClass的定義。 MEF將根據東西它「知道」這個組合參加辦法,並因爲它不知道「MyClass的」 ...

我注意到這一個:

[Export]  public MyClass SelectedMyClass { get; private set; } 

這意味着你正在試圖欺騙MEF成不時更新其中的一個部分?解決方案是創建一個包含「運行時」對象的自定義目錄,您可以在其中隨時更新MyClass的導出值。當前的實現永遠不會解析MyClass ...

[編輯]: 您也可以修飾一個成員,但是您必須在其中添加類類型。因此,這將工作:

[導出(typeof運算(MyClass的)]公共MyClass的SelectedMyClass {獲取;私人集;}

+0

不幸的是,似乎並沒有解決它:( – kennethkryger 2011-05-05 11:23:31