我知道這是AutoMapper而不是AutoMerge(R),但...合併兩個對象產生第三使用AutoMapper
我使用AutoMapper起步,並沒有必要地圖A - > B,並添加從C的一些屬性,使B成爲A + C的一種扁平合成。
這是可能的AutoMapper的我應該只使用AutoMapper做繁重的工作,然後手動映射額外的屬性?
我知道這是AutoMapper而不是AutoMerge(R),但...合併兩個對象產生第三使用AutoMapper
我使用AutoMapper起步,並沒有必要地圖A - > B,並添加從C的一些屬性,使B成爲A + C的一種扁平合成。
這是可能的AutoMapper的我應該只使用AutoMapper做繁重的工作,然後手動映射額外的屬性?
從我記憶中的AutoMapper中,您必須將您的映射定義爲一個輸出的一個輸入(也許這已經改變 - 因爲一個月沒有使用它)。
如果是這種情況下,也許你的映射應該是KeyValuePair<A,C>
(或某種物體的構成既甲& C)=>乙
這種方式可以具有一個定義的輸入參數映射到您的輸出對象
這不行嗎?
var mappedB = _mapper.Map<A,B>(aInstance);
_mapper.Map(instanceC,mappedB);
我不知道 - 是嗎? –
您可以用ValueInjecter
a.InjectFrom(b)
.InjectFrom(c)
.InjectFrom<SomeOtherMappingAlgorithmDefinedByYou>(dOrBOrWhateverObject);
我搜索艱辛而漫長的這個問題,並最終實現一個的對象合併在一起的擴展方法做到這一點。
我引用的步驟在我的博客http://twistyvortek.blogspot.com和下面的代碼:
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; } } }
用途包括方法鏈接,所以你可以合併多個對象爲一。
我會做的是使用automapper將來自各種源的部分屬性映射到相同類的DTO等,然後使用此擴展方法將它們合併在一起。
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);
希望這可以幫助別人。
我非常確定這不會編譯,定義擴展方法的類必須是非泛型的和靜態的,那麼MergeWith(這個T primary,T secondary)如何纔能有效? – SimonGates
該類是非泛型和靜態的。這是通用的方法,但這不是問題。 –
public static T MergeWith
在Owain Wraggs的EMC諮詢博客中,有一個使用autoMapper,here將多個源合併到目的地的好例子。
編輯:爲了防範舊的「死鏈接」症候羣,Owain的博客中的代碼的本質如下。
/// <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;
}
}
由此產生的調用代碼是很好的簡潔。
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);
}
複合物似乎是前進的方向,像使用現有的類太的想法 - 我給它一個嘗試。 –
我們幾乎總是做一個B - > BDto。我們不斷遇到命名衝突的問題,以嘗試自動合併事件。 –
我想對基於自動約定的方法進行映像確實很難(尤其是碰撞),但AutoMapper至少會允許您定義自己的函數/委託來用於映射,所以至少在這種情況下,手動做...並且它也不需要太多代碼 - 爲漂亮的實用程序拍攝! :) – saret