C# 使用键将列表映射到Automapper中的现有列表
Automapper可以轻松地处理将一个对象类型列表映射到另一个不同对象类型列表的操作,但是否可以使用ID作为键将其映射到现有列表?我没有找到比下面更好的方法 这里是来源和目的地C# 使用键将列表映射到Automapper中的现有列表,c#,automapper,automapper-2,C#,Automapper,Automapper 2,Automapper可以轻松地处理将一个对象类型列表映射到另一个不同对象类型列表的操作,但是否可以使用ID作为键将其映射到现有列表?我没有找到比下面更好的方法 这里是来源和目的地 public class Source { public int Id { get; set; } public string Foo { get; set; } } public class Destination { public int Id { get; set; } p
public class Source
{
public int Id { get; set; }
public string Foo { get; set; }
}
public class Destination
{
public int Id { get; set; }
public string Foo { get; set; }
}
定义转换器(您应该将列表更改为您正在使用的任何类型)
公共类CollectionConverter:ITypeConverter
{
公共列表转换(ResolutionContext上下文)
{
var destinationCollection=(List)context.DestinationValue;
if(destinationCollection==null)
destinationCollection=新列表();
var sourceCollection=(List)context.SourceValue;
foreach(sourceCollection中的变量源)
{
目的地匹配目的地=null;
foreach(destinationCollection中的var目标)
{
if(destination.Id==source.Id)
{
Mapper.Map(源、目的地);
匹配目的地=目的地;
打破
}
}
if(matchedDestination==null)
destinationCollection.Add(Mapper.Map(source));
}
返回目的地集合;
}
}
这里是实际的映射配置和示例
Mapper.CreateMap<Source,Destination>();
Mapper.CreateMap<List<Source>,List<Destination>>().ConvertUsing(new CollectionConverter());
var sourceCollection = new List<Source>
{
new Source{ Id = 1, Foo = "Match"},
new Source{ Id = 2, Foo = "DoesNotMatchWithDestination"}
};
var destinationCollection = new List<Destination>
{
new Destination{ Id = 1, Foo = "Match"},
new Destination{ Id = 3, Foo = "DoeNotMatchWithSource"}
};
var mergedCollection = Mapper.Map(sourceCollection, destinationCollection);
Mapper.CreateMap();
CreateMap().ConvertUsing(新的CollectionConverter());
var sourceCollection=新列表
{
新源{Id=1,Foo=“Match”},
新源{Id=2,Foo=“DoesNotMatchWithDestination”}
};
var destinationCollection=新列表
{
新目的地{Id=1,Foo=“Match”},
新目的地{Id=3,Foo=“DoeNotMatchWithSource”}
};
var mergedCollection=Mapper.Map(sourceCollection,destinationCollection);
您应该得到以下结果
我发现这篇文章非常有用,因此我想我会在类型转换器的通用版本中进行反馈,您可以使用它从每个对象中选择要匹配的属性 使用它,您只需执行以下操作:
// Example of usage
Mapper.CreateMap<UserModel, User>();
var converter = CollectionConverterWithIdentityMatching<UserModel, User>.Instance(model => model.Id, user => user.Id);
Mapper.CreateMap<List<UserModel>, List<User>>().ConvertUsing(converter);
//The actual converter
public class CollectionConverterWithIdentityMatching<TSource, TDestination> :
ITypeConverter<List<TSource>, List<TDestination>> where TDestination : class
{
private readonly Func<TSource, object> sourcePrimaryKeyExpression;
private readonly Func<TDestination, object> destinationPrimaryKeyExpression;
private CollectionConverterWithIdentityMatching(Expression<Func<TSource, object>> sourcePrimaryKey, Expression<Func<TDestination, object>> destinationPrimaryKey)
{
this.sourcePrimaryKeyExpression = sourcePrimaryKey.Compile();
this.destinationPrimaryKeyExpression = destinationPrimaryKey.Compile();
}
public static CollectionConverterWithIdentityMatching<TSource, TDestination>
Instance(Expression<Func<TSource, object>> sourcePrimaryKey, Expression<Func<TDestination, object>> destinationPrimaryKey)
{
return new CollectionConverterWithIdentityMatching<TSource, TDestination>(
sourcePrimaryKey, destinationPrimaryKey);
}
public List<TDestination> Convert(ResolutionContext context)
{
var destinationCollection = (List<TDestination>)context.DestinationValue ?? new List<TDestination>();
var sourceCollection = (List<TSource>)context.SourceValue;
foreach (var source in sourceCollection)
{
TDestination matchedDestination = default(TDestination);
foreach (var destination in destinationCollection)
{
var sourcePrimaryKey = GetPrimaryKey(source, this.sourcePrimaryKeyExpression);
var destinationPrimaryKey = GetPrimaryKey(destination, this.destinationPrimaryKeyExpression);
if (string.Equals(sourcePrimaryKey, destinationPrimaryKey, StringComparison.OrdinalIgnoreCase))
{
Mapper.Map(source, destination);
matchedDestination = destination;
break;
}
}
if (matchedDestination == null)
{
destinationCollection.Add(Mapper.Map<TDestination>(source));
}
}
return destinationCollection;
}
private string GetPrimaryKey<TObject>(object entity, Func<TObject, object> expression)
{
var tempId = expression.Invoke((TObject)entity);
var id = System.Convert.ToString(tempId);
return id;
}
}
//用法示例
CreateMap();
var converter=collectionconverterwhithidentitymatching.Instance(model=>model.Id,user=>user.Id);
CreateMap().ConvertUsing(转换器);
//实际转换器
公共类CollectionConverterWithidentialMatch:
ITypeConverter,其中TDestination:class
{
私有只读Func sourcePrimaryKeyExpression;
私有只读函数destinationPrimaryKeyExpression;
private CollectionConverter具有身份匹配(表达式sourcePrimaryKey、表达式destinationPrimaryKey)
{
this.sourcePrimaryKeyExpression=sourcePrimaryKey.Compile();
this.destinationPrimaryKeyExpression=destinationPrimaryKey.Compile();
}
公共静态收集转换器不匹配
实例(表达式sourcePrimaryKey、表达式destinationPrimaryKey)
{
返回新的CollectionConverterWithidentialMatching(
sourcePrimaryKey、destinationPrimaryKey);
}
公共列表转换(ResolutionContext上下文)
{
var destinationCollection=(List)context.DestinationValue??new List();
var sourceCollection=(List)context.SourceValue;
foreach(sourceCollection中的变量源)
{
TDestination matchedDestination=默认值(TDestination);
foreach(destinationCollection中的var目标)
{
var sourcePrimaryKey=GetPrimaryKey(source,this.sourcePrimaryKey表达式);
var destinationPrimaryKey=GetPrimaryKey(目的地,this.destinationPrimaryKeyExpression);
if(string.Equals(sourcePrimaryKey、destinationPrimaryKey、StringComparison.OrdinalIgnoreCase))
{
Mapper.Map(源、目的地);
匹配目的地=目的地;
打破
}
}
if(matchedDestination==null)
{
destinationCollection.Add(Mapper.Map(source));
}
}
返回目的地集合;
}
私有字符串GetPrimaryKey(对象实体,Func表达式)
{
var tempId=expression.Invoke((TObject)实体);
var id=System.Convert.ToString(tempId);
返回id;
}
}
// Example of usage
Mapper.CreateMap<UserModel, User>();
var converter = CollectionConverterWithIdentityMatching<UserModel, User>.Instance(model => model.Id, user => user.Id);
Mapper.CreateMap<List<UserModel>, List<User>>().ConvertUsing(converter);
//The actual converter
public class CollectionConverterWithIdentityMatching<TSource, TDestination> :
ITypeConverter<List<TSource>, List<TDestination>> where TDestination : class
{
private readonly Func<TSource, object> sourcePrimaryKeyExpression;
private readonly Func<TDestination, object> destinationPrimaryKeyExpression;
private CollectionConverterWithIdentityMatching(Expression<Func<TSource, object>> sourcePrimaryKey, Expression<Func<TDestination, object>> destinationPrimaryKey)
{
this.sourcePrimaryKeyExpression = sourcePrimaryKey.Compile();
this.destinationPrimaryKeyExpression = destinationPrimaryKey.Compile();
}
public static CollectionConverterWithIdentityMatching<TSource, TDestination>
Instance(Expression<Func<TSource, object>> sourcePrimaryKey, Expression<Func<TDestination, object>> destinationPrimaryKey)
{
return new CollectionConverterWithIdentityMatching<TSource, TDestination>(
sourcePrimaryKey, destinationPrimaryKey);
}
public List<TDestination> Convert(ResolutionContext context)
{
var destinationCollection = (List<TDestination>)context.DestinationValue ?? new List<TDestination>();
var sourceCollection = (List<TSource>)context.SourceValue;
foreach (var source in sourceCollection)
{
TDestination matchedDestination = default(TDestination);
foreach (var destination in destinationCollection)
{
var sourcePrimaryKey = GetPrimaryKey(source, this.sourcePrimaryKeyExpression);
var destinationPrimaryKey = GetPrimaryKey(destination, this.destinationPrimaryKeyExpression);
if (string.Equals(sourcePrimaryKey, destinationPrimaryKey, StringComparison.OrdinalIgnoreCase))
{
Mapper.Map(source, destination);
matchedDestination = destination;
break;
}
}
if (matchedDestination == null)
{
destinationCollection.Add(Mapper.Map<TDestination>(source));
}
}
return destinationCollection;
}
private string GetPrimaryKey<TObject>(object entity, Func<TObject, object> expression)
{
var tempId = expression.Invoke((TObject)entity);
var id = System.Convert.ToString(tempId);
return id;
}
}