2010-03-17 34 views
22

Tôi biết đó là AutoMapper và không AutoMerge (r), nhưng ...Hợp nhất hai đối tượng để sản xuất thứ ba sử dụng AutoMapper

Tôi đã bắt đầu sử dụng AutoMapper và có nhu cầu sử dụng Map A -> B, và để thêm một số thuộc tính từ C sao cho B trở thành một loại hỗn hợp phẳng của A + C.

Điều này có thể thực hiện được trong AutoMapper không? Tôi chỉ cần sử dụng AutoMapper để thực hiện việc nâng hạng nặng sau đó ánh xạ thủ công vào các thuộc tính bổ sung?

Trả lời

4

Từ những gì tôi nhớ với AutoMapper, bạn phải xác định ánh xạ của bạn là một đầu vào cho một đầu ra (có thể điều này đã thay đổi kể từ - chưa sử dụng nó trong nhiều tháng).

Nếu đây là trường hợp, có thể lập bản đồ của bạn nên có KeyValuePair<A,C> (hoặc một số loại đối tượng sáng tác cả A & C) => B

Bằng cách này bạn có thể có một bản đồ tham số đầu vào định nghĩa đối tượng outputted của bạn

+0

Đối tượng tổng hợp dường như là con đường phía trước, như ý tưởng sử dụng lớp hiện có - Tôi sẽ thử. –

+0

Chúng tôi khá nhiều luôn làm một B -> BDto. Chúng tôi chỉ tiếp tục gặp sự cố với các xung đột đặt tên để cố gắng tự động hợp nhất mọi thứ. –

+0

Tôi sẽ chụp ảnh phương pháp tiếp cận dựa trên quy ước tự động sẽ thực sự khó thực hiện (đặc biệt là với va chạm), nhưng AutoMapper ít nhất sẽ cho phép bạn xác định chức năng/đại biểu của riêng bạn để sử dụng cho ánh xạ, vì vậy ít nhất trong trường hợp này làm điều đó bằng tay ... và nó không mất nhiều mã hoặc - shot cho các tiện ích tốt đẹp! :) – saret

12

Điều này có hiệu quả không?

var mappedB = _mapper.Map<A,B>(aInstance); 
_mapper.Map(instanceC,mappedB); 
+16

Tôi không biết - phải không? –

14

Bạn có thể làm điều này với ValueInjecter

a.InjectFrom(b) 
    .InjectFrom(c) 
    .InjectFrom<SomeOtherMappingAlgorithmDefinedByYou>(dOrBOrWhateverObject); 
+4

Công cụ này rất tuyệt. – Merritt

+0

Sử dụng nó ngay bây giờ để lập bản đồ bó các đối tượng giống như khác nhau cho một thực thể EF. – Merritt

+1

@Omu, công cụ rất thú vị, tôi không chắc chắn, nếu bạn trả lời câu hỏi trên, mặc dù. – hgulyan

4

Tôi đã tìm kiếm cứng và dài về vấn đề này và kết thúc thực hiện một phương pháp mở rộng mà hợp nhất đối tượng của nhau.

tôi tham khảo các bước trên blog của tôi http://twistyvortek.blogspot.com và đây là đoạn code:

 

    using System; 

    namespace Domain.Models 
    { 
     public static class ExtendedMethods 
     { 
      /// <summary> 
      /// Merges two object instances together. The primary instance will retain all non-Null values, and the second will merge all properties that map to null properties the primary 
      /// </summary> 
      /// <typeparam name="T">Type Parameter of the merging objects. Both objects must be of the same type.</typeparam> 
      /// <param name="primary">The object that is receiving merge data (modified)</param> 
      /// <param name="secondary">The object supplying the merging properties. (unmodified)</param> 
      /// <returns>The primary object (modified)</returns> 
      public static T MergeWith<T>(this T primary, T secondary) 
      { 
       foreach (var pi in typeof (T).GetProperties()) 
       { 
        var priValue = pi.GetGetMethod().Invoke(primary, null); 
        var secValue = pi.GetGetMethod().Invoke(secondary, null); 
        if (priValue == null || (pi.PropertyType.IsValueType && priValue == Activator.CreateInstance(pi.PropertyType))) 
        { 
         pi.GetSetMethod().Invoke(primary, new[] {secValue}); 
        } 
       } 
       return primary; 
      } 
     } 
    } 

Cách sử dụng bao gồm phương pháp chaining vì vậy bạn có thể kết hợp nhiều đối tượng thành một.

Điều tôi sẽ làm là sử dụng automapper để ánh xạ một phần thuộc tính từ nhiều nguồn khác nhau của bạn vào cùng một lớp DTO, v.v. sau đó sử dụng phương pháp mở rộng này để hợp nhất chúng lại với nhau.

 

    var Obj1 = Mapper.Map(Instance1); 
    var Obj2 = Mapper.Map(Instance2); 
    var Obj3 = Mapper.Map(Instance3); 
    var Obj4 = Mapper.Map(Instance4); 

    var finalMerge = Obj1.MergeWith(Obj2) 
           .MergeWith(Obj3) 
           .MergeWith(Obj4); 

Hy vọng điều này sẽ giúp ai đó.

+1

Tôi khá chắc chắn rằng điều này sẽ không biên dịch, Lớp định nghĩa một phương thức mở rộng phải không chung chung và tĩnh sao cho MergeWith có thể hợp lệ (T chính, T thứ hai) hợp lệ? – SimonGates

+0

Lớp học không chung chung và tĩnh. Đó là phương pháp chung chung, nhưng đó không phải là vấn đề. –

+3

công cộng tĩnh T MergeWith (T này chính, T trung học) –

3

Có một ví dụ điển hình về việc hợp nhất nhiều nguồn vào đích bằng cách sử dụng autoMapper, here trong Blog tư vấn EMC của Owain Wraggs.

CHỈNH SỬA: Để bảo vệ chống lại hội chứng "liên kết chết" cũ, bản chất của mã trong blog của Owain ở bên dưới.

/// <summary> 
/// Helper class to assist in mapping multiple entities to one single 
/// entity. 
/// </summary> 
/// <remarks> 
/// Code courtesy of Owain Wraggs' EMC Consulting Blog 
/// Ref: 
///  http://consultingblogs.emc.com/owainwragg/archive/2010/12/22/automapper-mapping-from-multiple-objects.aspx 
/// </remarks> 
public static class EntityMapper 
{ 
    /// <summary> 
    /// Maps the specified sources to the specified destination type. 
    /// </summary> 
    /// <typeparam name="T">The type of the destination</typeparam> 
    /// <param name="sources">The sources.</param> 
    /// <returns></returns> 
    /// <example> 
    /// Retrieve the person, address and comment entities 
    /// and map them on to a person view model entity. 
    /// 
    /// var personId = 23; 
    /// var person = _personTasks.GetPerson(personId); 
    /// var address = _personTasks.GetAddress(personId); 
    /// var comment = _personTasks.GetComment(personId); 
    /// 
    /// var personViewModel = EntityMapper.Map<PersonViewModel>(person, address, comment); 
    /// </example> 
    public static T Map<T>(params object[] sources) where T : class 
    { 
     // If there are no sources just return the destination object 
     if (!sources.Any()) 
     { 
      return default(T); 
     } 

     // Get the inital source and map it 
     var initialSource = sources[0]; 
     var mappingResult = Map<T>(initialSource); 

     // Now map the remaining source objects 
     if (sources.Count() > 1) 
     { 
      Map(mappingResult, sources.Skip(1).ToArray()); 
     } 

     // return the destination object 
     return mappingResult; 
    } 

    /// <summary> 
    /// Maps the specified sources to the specified destination. 
    /// </summary> 
    /// <param name="destination">The destination.</param> 
    /// <param name="sources">The sources.</param> 
    private static void Map(object destination, params object[] sources) 
    { 
     // If there are no sources just return the destination object 
     if (!sources.Any()) 
     { 
      return; 
     } 

     // Get the destination type 
     var destinationType = destination.GetType(); 

     // Itereate through all of the sources... 
     foreach (var source in sources) 
     { 
      // ... get the source type and map the source to the destination 
      var sourceType = source.GetType(); 
      Mapper.Map(source, destination, sourceType, destinationType); 
     } 
    } 

    /// <summary> 
    /// Maps the specified source to the destination. 
    /// </summary> 
    /// <typeparam name="T">type of teh destination</typeparam> 
    /// <param name="source">The source.</param> 
    /// <returns></returns> 
    private static T Map<T>(object source) where T : class 
    { 
     // Get thr source and destination types 
     var destinationType = typeof(T); 
     var sourceType = source.GetType(); 

     // Get the destination using AutoMapper's Map 
     var mappingResult = Mapper.Map(source, sourceType, destinationType); 

     // Return the destination 
     return mappingResult as T; 
    } 
} 

Mã gọi điện kết quả là đẹp gọn gàng.

public ActionResult Index() 
    { 

     // Retrieve the person, address and comment entities and 
     // map them on to a person view model entity 
     var personId = 23; 

     var person = _personTasks.GetPerson(personId); 
     var address = _personTasks.GetAddress(personId); 
     var comment = _personTasks.GetComment(personId); 

     var personViewModel = EntityMapper.Map<PersonViewModel>(person, address, comment); 

     return this.View(personViewModel); 
    } 
Các vấn đề liên quan