2011-10-15 26 views
37

Tôi đã bắt đầu sử dụng https://github.com/robconery/massive cho một dự án, tôi tự hỏi liệu có công cụ lập bản đồ nào cho phép hỗ trợ ánh xạ động tới tĩnh không?Cho phép ánh xạ các loại động bằng AutoMapper hoặc tương tự?

Tôi đã sử dụng AutoMapper trước đây, AutoMapper có hỗ trợ tính năng này không?

Tôi biết về chức năng DynamicMap từ AutoMapper, tuy nhiên tôi tin rằng chức năng này là để chạy bản đồ mà không cần tạo Bản đồ trước. Trong ví dụ của tôi dưới đây nó không hoạt động.

dynamic curUser = users.GetSingleUser(UserID); 
var retUser = Mapper.DynamicMap<UserModel>(curUser); 
users.GetSingleUser(UserID); // returns a dynamic object 
+0

Xem [q này] (http://stackoverflow.com/questions/19529178/recursively-mapping-expandoobject) để có câu trả lời hoàn chỉnh hơn. – nawfal

+0

@LiamB, "AutoMapper có hỗ trợ điều này không?" - bạn có nghĩa là lập bản đồ tự động giữa các thuộc tính với các tên giống nhau/tương tự? Hoặc bản đồ của bạn phức tạp hơn? –

+0

@LeonidVasilyev Xin lỗi - Tôi không chắc, câu hỏi này là 4 tuổi! :) – LiamB

Trả lời

58

AutoMapper 4.2.0 bây giờ hỗ trợ Dynamic/expando/dictionary mapping

Với tính năng này, bạn có thể ánh xạ các đối tượng expando của bạn với các loại tĩnh:

phiên bản
dynamic CurUser = _users.GetSingleUser(UserID); 
var config = new MapperConfiguration(cfg => { }); 
var mapper = config.CreateMapper(); 

var retUser = mapper.Map<UserModel>(CurUser); 

Cũ của AutoMapper không hỗ trợ này (Massive nội bộ sử dụng ExpandoObject không cung cấp thuộc tính nào) và bạn đang ở bên phải Mapper.DynamicMap là để lập bản đồ mà không cần tạo cấu hình ánh xạ.

Trên thực tế nó không phải là khó để viết cho mình một mapper nếu bạn chỉ muốn bản đồ đơn giản:

public static class DynamicToStatic 
{ 
    public static T ToStatic<T>(object expando) 
    { 
     var entity = Activator.CreateInstance<T>(); 

     //ExpandoObject implements dictionary 
     var properties = expando as IDictionary<string, object>; 

     if (properties == null) 
      return entity; 

     foreach (var entry in properties) 
     { 
      var propertyInfo = entity.GetType().GetProperty(entry.Key); 
      if(propertyInfo!=null) 
       propertyInfo.SetValue(entity, entry.Value, null); 
     } 
     return entity; 
    } 
} 

dynamic CurUser = _users.GetSingleUser(UserID); 
var retUser = DynamicToStatic.ToStatic<UserModel>(CurUser); 
+0

Tôi đã đấu tranh với điều này trong nhiều giờ chiều nay +1. Cảm ơn – abarr

+4

@nemesv "[...] ExpandoObject không cung cấp thuộc tính nào có) [...]" <--- ExpandoObject triển khai 'IDictionary ' để bạn có thể truyền tới giao diện này và sử dụng 'ContainsKey'. –

17

Hãy thử Slapper.AutoMapperhttps://github.com/randyburden/Slapper.AutoMapper

Slapper.AutoMapper bản đồ dữ liệu động để loại tĩnh

Nó hoạt động cho cả hai dynamicDictionary<A, B> thật tuyệt vời.

Dưới đây là một ví dụ (lấy từ URL ở trên) cho thấy cách dễ dàng nó làm việc với từ điển:

public class Person 
{ 
    public int Id; 
    public string FirstName; 
    public string LastName; 
} 

[Test] 
public void CanMapMatchingFieldNamesWithEase() 
{ 
    // Arrange 
    var dictionary = new Dictionary<string, object> 
          { 
           { "Id", 1 }, 
           { "FirstName", "Clark" }, 
           { "LastName", "Kent" } 
          }; 

    // Act 
    var person = Slapper.AutoMapper.Map<Person>(dictionary); 

    // Assert 
    Assert.NotNull(person); 
    Assert.That(person.Id == 1); 
    Assert.That(person.FirstName == "Clark"); 
    Assert.That(person.LastName == "Kent"); 
} 
+0

Điều này làm việc với các cấu trúc phân cấp sâu, nhưng aah .. quy ước '_' là một dấu gạch ngang ..: ( – nawfal

+0

quy ước đặt tên thử nghiệm được cập nhật ...;) –

+1

nooooooooo, tôi không có nghĩa là tên của phương thức của bạn. Ý tôi là, đây là một thư viện sẽ làm việc với cấu trúc phân cấp sâu trong cấu trúc lớp (cấu trúc lớp phức tạp không giống như ví dụ trong câu trả lời của bạn), không giống như câu trả lời được chấp nhận, nhưng nó đòi hỏi một "quy ước đặt tên" nhất định để làm việc. Xem liên kết để biết ví dụ. – nawfal

3

Giả khuôn khổ bạn sử dụng lợi nhuận ExpandoObject bạn có thể đạt được một số loại bản đồ động sử dụng AutoMapper:

Mapper.CreateMap<ExpandoObject, UserModel>() 
    .ForAllMembers((options) => options.ResolveUsing((resolution) => 
     { 
      var dictionary = (IDictionary<string, object>) resolution.Context.SourceValue; 
      return dictionary[resolution.Context.MemberName]; 
     })); 
... 
dynamic CurUser = _users.GetSingleUser(UserID); 
var retUser = Mapper.Map<UserModel>(CurUser); 

Bạn có thể tạo bất kỳ loại bản đồ phức tạp sử dụng các phương pháp ConstructUsing ..

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