2010-01-05 25 views
36

Tôi đang cố gắng tìm ra thuộc tính Constructor Injection của MEF. Tôi không có ý tưởng làm thế nào tôi nói với nó để tải các tham số của nhà xây dựng.MEF Constructor Injection

này là tài sản Tôi đang cố gắng để tải

[ImportMany(typeof(BUsers))] 
public IEnumerable<BUsers> LoadBUsers { get; set; } 

Đây là mã tôi đang sử dụng để nhập khẩu các hội đồng.

try 
{ 
    var catalog = new AggregateCatalog(); 
    catalog.Catalogs.Add(new AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly())); 
    catalog.Catalogs.Add(new DirectoryCatalog("DI")); 
    var container = new CompositionContainer(catalog); 
    container.ComposeParts(this); 
} 

Đây là lớp tôi đang cố gắng để tải

[Serializable] 
[Export(typeof(BUsers))] 
public class EditProfile : BUsers 
{ 
    [ImportingConstructor] 
    public EditProfile(string Method, string Version) 
    {    
     Version = "2"; 
     Action = "Edit"; 
     TypeName = "EditProfile"; 
    } 

Trả lời

53

Khi bạn sử dụng thuộc tính ImportingConstructor, các thông số để các nhà xây dựng trở thành hàng nhập khẩu. Theo mặc định, những gì bạn đang nhập (tên hợp đồng) được dựa trên loại tham số hoặc thuộc tính mà bạn đang nhập vào. Vì vậy, trong trường hợp này, loại hợp đồng cho cả nhập khẩu của bạn là chuỗi và không có sự khác biệt thực sự giữa thông số đầu tiên và thứ hai.

Dường như bạn đang cố gắng sử dụng hàng nhập để cung cấp giá trị cấu hình, không nhất thiết phải là giá trị được thiết kế. Để làm điều bạn muốn, bạn nên ghi đè tên hợp đồng cho từng tham số, như sau:

[ImportingConstructor] 
public EditProfile([Import("Method")] string Method, [Import("Version")] string Version) 
{ } 

Sau đó, bạn cần xuất cho Phương thức và phiên bản trong vùng chứa của mình. Một cách để làm điều này chỉ là thêm chúng trực tiếp:

var container = new CompositionContainer(catalog); 
container.ComposeExportedValue("Method", "MethodValue"); 
container.ComposeExportedValue("Version", "2.0"); 
container.ComposeParts(this); 

(Lưu ý rằng ComposeExportedValue thực sự là một phương pháp mở rộng định nghĩa trên lớp AttributedModelServices tĩnh.)

Nếu bạn muốn đọc các giá trị từ một cấu hình tập tin của một số loại, bạn có thể tạo nhà cung cấp xuất khẩu của riêng bạn mà đọc cấu hình và cung cấp các giá trị trong nó như là xuất khẩu vào container.

Một cách khác để xử lý việc này là chỉ nhập một giao diện cung cấp quyền truy cập vào các giá trị cấu hình theo tên và nhận các giá trị bạn cần từ phần thân của hàm tạo.

+0

Tôi vừa tải xuống tệp mới tại CodePlex. Phương thức ComposeExportedValue() không có trong lớp của CompositionContainer. Nó đâu rồi? –

+0

Tôi nghĩ tôi đã tìm ra phương pháp. Nó nằm trong lớp AttributedModelServices, trong đó phương thức được định nghĩa là phương thức mở rộng cho lớp CompositionContainer. –

+1

@ David.Chu.ca Có, ComposeExportedValue là một phương thức mở rộng trên lớp AttributedModelServices. –

23

Tôi thích giải pháp của Daniel; tuy nhiên, chỉ có một điều tôi thấy là khớp nối chặt chẽ giữa các tên tham số giữa tác nhân (người tạo CompopositionContrainer()) và xuất khẩu phần với [ImportingConstructor] cho CTOR tùy chỉnh. Ví dụ: "Phương thức" có hai được đối sánh ở cả hai vị trí. Nó làm cho khó khăn để duy trì phần xuất khẩu nếu các diễn viên và xuất khẩu một phần là trong các dự án khác nhau.

Nếu có thể, tôi sẽ thêm CTOR thứ hai vào lớp phần Xuất. Ví dụ:

[Export(typeof(BUsers))] 
public class EditProfile : BUsers 
{ 
    [ImportingConstructor] 
    public EditProfile(EditProfileParameters ctorPars) 
    : this(ctorPars.Method, ctorPars.Version) {} 

    public EditProfile(string Method, string Version) 
    { 
     Version = "2"; 
     Action = "Edit"; 
     TypeName = "EditProfile"; 
    } 

Lớp của EditProfileParameters nên đơn giản: hai thuộc tính của Phương pháp và Version:

[Export] 
public class EditProfileParameters{ 
    public string Method { get; set; } 
    public string Version { get; set; } 
} 

Điểm mấu chốt là để thêm thuộc tính xuất khẩu đến lớp. Sau đó, MEF có thể ánh xạ lớp này thành tham số của CTOR của EditProfile.

Dưới đây là ví dụ để thêm phần Xuất khẩu sang container:

var container = new CompositionContainer(catalog); 
var instance1 = new EditProfileParameters(); 
// set property values from config or other resources 
container.ComposeExportedValue(instance1); 
container.ComposeParts(this); 
0

Mặc dù muộn để các trò chơi, đây là một cách tiếp cận đó thúc đẩy một tính năng ít được biết đến của MEF: Xuất khẩu tài sản

public class ObjectMother 
{ 
    [Export] 
    public static EditProfile DefaultEditProfile 
    { 
     get 
     { 
      var method = ConfigurationManager.AppSettings["method"]; 
      var version = ConfigurationManager.AppSettings["version"]; 

      return new EditProfile(method,version); 
     } 
    } 
} 

Không có yêu cầu sử dụng cho ObjectMother để làm việc này, và không có thuộc tính nào được yêu cầu trên EditProfile.

+0

Tính năng tuyệt vời nhưng nếu 'EditProfile' chứa bất kỳ nhập khẩu nào? Trong trường hợp đó, bạn cần gọi 'SatisfyImportsOnce' trên vùng chứa. Đau đấy. Hiện tại tôi không có giải pháp thực sự cho vấn đề đó. –

+0

Trong trường hợp này, chúng tôi đang xây dựng một nhà máy tự tạo InstantProfile của bạn. Nếu EditProfile yêu cầu các phụ thuộc bổ sung trong hàm tạo, bạn luôn có thể mang các phụ thuộc đó vào trong Nhà máy thông qua một ImportingConstructor. Tôi nên chỉ ra rằng nếu bạn thêm các phụ thuộc bổ sung vào EditProfile, đây là tham chiếu duy nhất trong ứng dụng của bạn tới hàm tạo này và bạn sẽ nhận được các lỗi thời gian biên dịch. Đó là một thương mại công bằng, IMHO. – bryanbcook