2012-05-09 32 views
5

Tôi đã có một Dictionary<User, bool>AutoMapper điển phẳng

tài khoản như sau:

public class User { 
    public string Username { get; set; } 
    public string Avatar { get; set; 
} 

Loại thứ hai, bool, cho biết thành viên này là một người bạn của đăng nhập tài khoản. Tôi muốn flatten từ điển này vào một List<UserDto> UserDto được định nghĩa là:

public class UserDto { 
    public string Username { get; set; } 
    public string Avatar { get; set; } 
    public bool IsFriend { get; set; } 
} 

IsFriend đại diện cho giá trị của từ điển.

Tôi làm cách nào để thực hiện việc này?

+0

Nếu bất cứ ai có thể cung cấp cho tôi phương pháp thực sự sử dụng tự động hóa, tôi sẽ thay đổi câu trả lời cho câu hỏi! – reach4thelasers

Trả lời

11

Bạn sẽ có thể làm được điều này chỉ với một bản đồ :

Bạn cần để ánh xạ một KeyValuePair<User, bool>-UserDto. Điều này là cần thiết cho AutoMapper để có thể ánh xạ nội dung của từ điển đến nội dung của List<T> mà chúng ta đang tạo ra cuối cùng (có thể tìm thêm giải thích trong this answer).

Mapper.CreateMap<KeyValuePair<User, bool>, UserDto>() 
    .ForMember(dest => dest.Username, opt => opt.MapFrom(src => src.Key.UserName)) 
    .ForMember(dest => dest.Avatar, opt => opt.MapFrom(src => src.Key.Avatar)) 
    .ForMember(dest => dest.IsFriend, opt => opt.MapFrom(src => src.Value)); 

Sau đó, sử dụng các bản đồ trong .Map cuộc gọi của bạn:

Mapper.Map<Dictionary<User, bool>, List<UserDto>>(...); 

Bạn không cần phải để lập bản đồ các bộ sưu tập bản thân, như AutoMapper có thể xử lý lập bản đồ Dictionary đến một List miễn là bạn' ve ánh xạ các nội dung của các bộ sưu tập với nhau (trong trường hợp của chúng tôi, KeyValuePair<User, bool> đến UserDto).


Sửa: Đây là một giải pháp mà không yêu cầu lập bản đồ mỗi User tài sản để UserDto:

Mapper.CreateMap<User, UserDto>(); 
Mapper.CreateMap<KeyValuePair<User, bool>, UserDto>() 
    .ConstructUsing(src => Mapper.Map<User, UserDto>(src.Key)) 
    .ForMember(dest => dest.IsFriend, opt => opt.MapFrom(src => src.Value)); 

Sử dụng AutoMapper 2.0

+0

Giải pháp này yêu cầu bất kỳ lúc nào tôi thêm thuộc tính vào User & UserDto tôi cần phải thay đổi ánh xạ. Tôi muốn có một giải pháp mà không yêu cầu các thuộc tính cá nhân được ánh xạ. Nó không phải như thế nào automapper là nghĩa vụ phải làm việc. – reach4thelasers

+1

Nếu "đó không phải là cách tự động hóa được cho là hoạt động" thì tại sao API lại cung cấp phương thức '.ForMember'? Tuy nhiên, tôi sẽ thử một giải pháp "tự động" hơn. –

+1

@ reach4thelasers: Tôi đã thêm một giải pháp khác mà tôi cho rằng có thể hơi tự động hơn một chút –

-1

Đối với một cái gì đó đơn giản như thế này, một truy vấn LINQ nhanh sẽ thực hiện. Giả sử dictDictionary<User,bool> của bạn:

var conv = from kvp in dict 
      select new UserDto 
        { 
         Avatar = kvp.Key.Avatar, 
         IsFriend = kvp.Value, 
         Username = kvp.Key.Username 
        }; 
0

Tôi biết tôi cuối cho trò chơi, nhưng điều này có vẻ là một giải pháp chung chung hơn để lập bản đồ từ điển sang loại .Net (si mple) sử dụng automapper

public static IMappingExpression<Dictionary<string, string>, TDestination> ConvertFromDictionary<TDestination>(
     this IMappingExpression<Dictionary<string, string>, TDestination> exp) 
{ 
    foreach (PropertyInfo pi in typeof(TDestination).GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) 
    { 
     exp.ForMember(propertyName, cfg => cfg.MapFrom(r => r[propertyName])); 
    } 
    return exp; 
} 

Sử dụng nó như thế này

Mapper.CreateMap<Dictionary<string, string>, TDestination>().ConvertFromDictionary(); 

nơi TDestination thể một kiểu đơn giản NET. Đối với các loại phức tạp, bạn có thể cung cấp cho đại biểu Func/Action và bản đồ sử dụng chức năng đó. (Bên trong bên trên cho mỗi)

Ví dụ:

if (customPropNameMapFunc != null && !string.IsNullOrEmpty(customPropNameMapFunc(propertyName))) 
{ 
    exp.ForMember(propertyName, cfg => cfg.MapFrom(r => r[customPropNameMapFunc(propertyName)])); 
} 
Các vấn đề liên quan