2010-11-17 40 views
17

Tôi hiện đang có các bản đồ sau:Automapper cùng với Dependency Injection

Mapper.CreateMap<Journal, JournalDto>(); 

Bây giờ, Journal chứa một thành viên mang tên RefTypeID, mà giá trị tương ứng tồn tại trong một bảng trong cơ sở dữ liệu; để tra cứu giá trị này, tôi có một dịch vụ xử lý yêu cầu int -> string đơn giản. Cấu hình automapper hiện đang xảy ra trong một lớp tĩnh ở đầu chương trình. Có ổn không khi di chuyển mã ánh xạ vào một lớp được đưa vào vùng chứa DI của tôi hoặc có cách nào tốt hơn không?

+0

Lý do duy nhất tôi có thể nghĩ là không hoàn toàn là tổ chức. Bạn sẽ có khả năng có mã bản đồ trên tất cả (các) dự án của bạn. Nếu đối tượng miền của bạn thay đổi hoặc dtos có thể ít hơn lý tưởng. Nhưng tôi tò mò muốn tìm hiểu ý kiến ​​của người khác. – Daniel

+0

Vâng, tôi vẫn sẽ giữ mã bản đồ ở một nơi - tức là.lớp đó, sẽ lấy tất cả các dịch vụ cần thiết từ thùng chứa DI. Tôi chỉ cần phải khởi tạo bản đồ bản thân thay vì có thể dựa vào các nhà xây dựng tĩnh thực hiện nó tự động. – Femaref

+0

Đối với phiên bản mới nhất, hãy xem [this] (http://stackoverflow.com/a/35431096/1977871) để trả lời – VivekDev

Trả lời

8

Dưới đây là cách tôi giải quyết nó:

tôi định nghĩa một giao diện IMappingCreator:

public interface IMappingCreator 
{ 
    void CreateMappings(); 
} 

tôi đã đi trước và thực hiện một lớp học với giao diện mà (Tôi đang sử dụng MEF như DI container, đó là nơi các thuộc tính được đến từ) được đưa vào container DI như IMappingCreator:

[Export(typeof(IMappingCreator))] 
    public class Mapping : IMappingCreator 
    { 
     private readonly IRefTypesLookup iRefTypesLookup; 


     [ImportingConstructor] 
     public Mapping(IRefTypesLookup rtl) 
     { 
      iRefTypesLookup = rtl; 
     } 

     public void CreateMappings() 
     { 
      Mapper.CreateMap<Journal, DisplayJournal>().AfterMap((j, dj) => dj.RefTypeName = iRefTypesLookup.Lookup(j.RefTypeID)); 
     } 
    } 

Cuối cùng, trong khi khởi động ứng dụng của tôi, tôi lấy tất cả instanc es của giao diện mà trong container và gọi phương thức CreateMappings trên chúng:

var mappings = container.GetExportedValues<IMappingCreator>(); 

    foreach (IMappingCreator mc in mappings) 
    { 
     mc.CreateMappings(); 
    } 

Điều này làm cho các thiết lập ban đầu khá dễ dàng, như tất cả các sáng tạo xảy ra ở một nơi, và bạn có thể có nhiều người sáng tạo lập bản đồ theo ý muốn (tuy nhiên, bạn nên giữ chúng ở mức tối thiểu, có thể một lần cho mỗi dự án hoặc như vậy, lấy tất cả các dịch vụ cần thiết để ánh xạ các loại cụ thể trong dự án đó).

+0

Điều này khá hay ... Tôi có thể phải vay từ điều này! : D MEF là một bổ sung tuyệt vời cho khuôn khổ. – Daniel

+0

cảm thấy tự do, tôi không nghĩ rằng tôi là người duy nhất đi lên chống lại vấn đề này. – Femaref

14

Cách tốt hơn là sử dụng một trình giải quyết của khách hàng. cấu hình bản đồ được thiết kế để được tĩnh, vì vậy phân giải tùy chỉnh được thiết kế để cung cấp bản đồ cho một thành viên duy nhất:

Mapper.Initialize(cfg => { 
    cfg.ConstructServicesUsing(type => WhateverMefUsesToGetInstances.GetInstance(type)); 

    cfg.CreateMap<Journal, DisplayJournal>() 
     .ForMember(dest => dest.RefTypeName, 
      opt => opt.ResolveUsing<RefTypeNameResolver>()); 
}); 

Sau đó giải quyết của bạn trở thành:

[Export(typeof(IRefTypeNameResolver))] 
public class RefTypeNameResolver : ValueResolver<Journal, string>, IRefTypeNameResolver 
{ 
    private readonly IRefTypesLookup iRefTypesLookup; 

    [ImportingConstructor] 
    public RefTypeNameResolver (IRefTypesLookup rtl) 
    { 
     iRefTypesLookup = rtl; 
    } 

    protected override string ResolveCore(Journal source) 
    { 
     return iRefTypesLookup.Lookup(source.RefTypeID); 
    } 
} 

Cấu hình cần thực hiện một lần, đó là lý do tại sao API cấu hình cung cấp các móc nối vào API thực thi (các trình chuyển đổi loại, các giải pháp giá trị, v.v.)

+1

Tôi biết về ValueResolver, nhưng tôi nghĩ chúng vô dụng vì tôi thiếu cấu hình ConstructServicesUsing. Đẹp nhất! – Kugel

1

Đây là cách mới nhất để thực hiện ...

https://pintoservice.wordpress.com/2016/01/31/dependency-injection-for-automapper-4-2-in-asp-net-vnext-mvc-project/

Mặc dù cá nhân tôi thêm ánh xạ tự động trong bộ điều khiển, không phải trong kho lưu trữ. Bằng cách này bạn có thể sử dụng cùng một kho lưu trữ cho các bộ điều khiển khác nhau và có ánh xạ khác nhau. Cùng một khái niệm mặc dù, chỉ cần tiêm IMapper trong bộ điều khiển thay vì kho lưu trữ.

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