2009-12-04 24 views
20

Tôi cố gắng dành thời gian để hoàn thành công việc bằng MEF nhưng bây giờ, tôi gặp phải vấn đề cần được giúp đỡ.Nhập tài sản luôn rỗng (vấn đề nhập MEF)

Mô tả: Tôi có 2 tệp DLL và một tệp EXE. ClassLibrary1 (LoggerImpl.cs, SomeClass.cs) ClassLibrary2 (ILogger.cs) WindowsApplicationForms1 (WindowsApplicaitonForms1.cs, Program.cs)

Tôi cần bất kỳ sự giúp đỡ hoặc hướng tại sao điều này không hoạt động?

// ClassLibrary1.dll 
//SomeClass.cs 
public class SomeClass 
    { 
     [Import("Logging", typeof(ILogger))] 
     public ILogger Log { get; set; } <-- ALWAYS NULL ??? 

     public void Print() 
     { 
      Log.Print(); 
     } 

    } 

// ClassLibrary1.dll 
// LoggerImpl.cs 
namespace ClassLibrary1 
{ 
    [Export("Logging", typeof (ILogger))] 
    public class LoggerImpl : ILogger 
    { 
     public void Print() 
     { 
      Console.WriteLine("print called"); 
     } 
    } 
} 

// ClassLibrary2.dll 
// ILogger.cs 
namespace LogNamespace 
{ 
    public interface ILogger 
    { 
     void Print(); 
    } 
} 

// WindowsFormsApplication1.exe 
// WindowsFormsApplication1.cs 
namespace WindowsFormsApplication1 
{ 
    [Export("Form1",typeof(Form1))] 
    public partial class Form1 : Form 
    { 

     [Import("Logging", typeof(ILogger))] 
     public ILogger Log { set; get; } 

     private CompositionContainer _container; 

     public Form1() 
     { 
      InitializeComponent(); 
      Compose(); 
      Log.Print(); 

      SomeClass c = new SomeClass(); 
      c.Print(); 
     } 

     private void Compose() 
     { 
      var catalog = new AggregateCatalog(); 

      catalog.Catalogs.Add(new DirectoryCatalog(".")); 
      catalog.Catalogs.Add(new AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly())); 
      _container = new CompositionContainer(catalog); 

      try 
      { 
       _container.ComposeParts(this); 
      } 
      catch (CompositionException compositionException) 
      { 
       MessageBox.Show(compositionException.ToString()); 
      } 
     } 
    } 
} 
+2

'SomeClass' của bạn không tham gia vào sáng tác, vì vậy sẽ không bao giờ được nhập. – dtb

Trả lời

27

Nếu bạn tạo một đối tượng mới của một lớp mình (new SomeClass()), container sẽ không biết gì về nó và sẽ không sáng tác nó.

Đối với một phần được sáng tác bởi MEF, nó cần phải được tạo bởi MEF hoặc được chuyển một cách rõ ràng đến vùng chứa. Bạn có thể tự nói với MEF để đáp ứng nhập khẩu đối tượng SomeClass trong giống như cách bạn nói với nó để đáp ứng nhập khẩu của dạng:

SomeClass c = new SomeClass(); 
_container.SatisfyImports(c); 
c.Print(); 

Tuy nhiên, bạn cần truy cập trực tiếp đến các container để làm điều này, vì vậy nó không hoạt động cũng như bên ngoài lớp Form1 của bạn. Nói chung, cách tốt hơn để làm điều đó là xuất SomeClass và tạo một lần nhập trong lớp Form1 của bạn cho SomeClass:

[Export] 
public class SomeClass 
{ 
    [Import("Logging", typeof(ILogger))] 
    public ILogger Log { get; set; } 

    // etc. 
} 

public partial class Form1 : Form 
{ 
    [Import("Logging", typeof(ILogger))] 
    public ILogger Log { set; get; } 

    [Import] 
    SomeClass _someClass { get; set; } 

    // etc. 
} 
+0

+1. Vấn đề chính là SomeClass không có vùng chứa thành phần. Nếu SomeClass được biến thành một giao diện, một số ví dụ có thể được sử dụng cùng với thuộc tính ImportMany để nó trở thành một cách đơn giản để thêm các phần bằng cách chỉ cần thả các assembly vào thư mục w/o mã bổ sung. – JamesEggers

1

Bạn cần một tuyên bố như thế tương tự như sau để liên quan đến việc SomeClass trong quá trình sáng tác

// ClassLibrary1.dll 
//SomeClass.cs 
using System; 
using System.ComponentModel.Composition; 
using System.ComponentModel.Composition.Hosting; 
using System.Windows.Forms; 
using LogNamespace; 

public class SomeClass 
{ 
    [Import("Logging", typeof(ILogger))] 
    public ILogger Log { get; set; } //<-- ALWAYS NULL ??? 

    public SomeClass() 
    { 
     var catalog = new AggregateCatalog(); 
     CompositionContainer _container; 

     // catalog.Catalogs.Add(new DirectoryCatalog(".")); 
     catalog.Catalogs.Add(new AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly())); 
     _container = new CompositionContainer(catalog); 

     _container.ComposeParts(this); 
    } 

    public void Print() 
    { 
     Log.Print(); 
    } 

} 

// ClassLibrary1.dll 
// LoggerImpl.cs 
namespace ClassLibrary1 
{ 
    [Export("Logging", typeof(ILogger))] 
    public class LoggerImpl : ILogger 
    { 
     public void Print() 
     { 
      Console.WriteLine("print called"); 
     } 
    } 
} 

// ClassLibrary2.dll 
// ILogger.cs 
namespace LogNamespace 
{ 
    public interface ILogger 
    { 
     void Print(); 
    } 
} 

// WindowsFormsApplication1.exe 
// WindowsFormsApplication1.cs 
namespace WindowsFormsApplication1 
{ 
    [Export("Form1", typeof(Form1))] 
    public partial class Form1 : Form 
    { 

     [Import("Logging", typeof(ILogger))] 
     public ILogger Log { set; get; } 

     private CompositionContainer _container; 

     public Form1() 
     { 
      InitializeComponent(); 
      Compose(); 
      Log.Print(); 

      SomeClass c = new SomeClass(); 
      c.Print(); 
     } 

     private void Compose() 
     { 
      var catalog = new AggregateCatalog(); 

      // catalog.Catalogs.Add(new DirectoryCatalog(".")); 
      catalog.Catalogs.Add(new AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly())); 
      _container = new CompositionContainer(catalog); 

      try 
      { 
       _container.ComposeParts(this); 
      } 
      catch (CompositionException compositionException) 
      { 
       MessageBox.Show(compositionException.ToString()); 
      } 
     } 
    } 
} 
+0

Cảm ơn bạn đã trả lời. Vì vậy, nếu tôi thêm một DLL với các bộ phận, tôi cũng phải thay đổi mã khách hàng (đọc phương pháp soạn) để bao gồm những phần? Tôi đã nghĩ rằng nếu tôi tạo một phần khác và đưa vào thư mục với ứng dụng, ứng dụng có thể sử dụng các phần đó nếu bản thân ứng dụng chứa Nhập phù hợp (như Meni, Logger, Thanh công cụ, v.v.). – ITGoran

+2

Trong mã này, bạn đang tạo hai thùng chứa riêng biệt, có thể không phải là thứ bạn muốn. Với hai thùng chứa, bạn sẽ nhận được hai trường hợp riêng biệt của trình ghi nhật ký trong lớp Form1 của bạn và SomeClass của bạn. –

Các vấn đề liên quan