考虑使用ViewModel:
public class ViewModel
{
public int id {get;set;}
public int a {get;set;}
public int b {get;set;}
}
和这样的原始模型:
public class Model
{
public int id {get;set;}
public int a {get;set;}
public int b {get;set;}
public int c {get;set;}
public virtual Object d {get;set;}
}
每次我获得视图模型时,我必须将所有ViewModel属性逐个放入Model中。就像是 :
var model = Db.Models.Find(viewModel.Id);
model.a = viewModel.a;
model.b = viewModel.b;
Db.SaveChanges();
这总会导致很多问题。我甚至有时会忘记提及一些属性然后发生灾难!我在寻找类似的东西:
Mapper.Map(model, viewModel);
BTW:我只使用automapper将Model转换为ViewModel,但反之亦然,我总是面临错误。
总体而言,这可能不是您正在寻找的答案,但这是AutoMapper作者的引用:
我不能为我的生活理解为什么我要将DTO直接转回模型对象。
我相信从ViewModel映射到Entity的最佳方法是不使用AutoMapper。 AutoMapper是一个很好的工具,用于映射对象而不使用静态以外的任何其他类。否则,每个添加的服务都会使代码变得更加混乱和混乱,并且在某些时候您将无法跟踪导致您的字段更新,集合更新等的原因。
经常面临的具体问题:
var target = new Target();
Mapper.Map(source1, target);
Mapper.Map(source2, target);
//etc..
该代码会导致错误,因为您无法将source1和source2映射到一起,并且映射可能取决于将源类映射到目标的顺序。如果您忘记进行1次映射,或者如果您的地图在1个属性上存在冲突的映射,并且相互覆盖,我就不会说话。这些问题可能看起来很小,但是在我使用自动化库来将ViewModel / Dto映射到Entity的几个项目中,它比从未使用过更加痛苦。
以下是一些链接:
为此,我们编写了一个简单的映射器。它按名称映射并忽略虚拟属性(因此它适用于实体框架)。如果要忽略某些属性,请添加PropertyCopyIgnoreAttribute。
用法:
PropertyCopy.Copy<ViewModel, Model>(vm, dbmodel);
PropertyCopy.Copy<Model, ViewModel>(dbmodel, vm);
码:
public static class PropertyCopy
{
public static void Copy<TDest, TSource>(TDest destination, TSource source)
where TSource : class
where TDest : class
{
var destProperties = destination.GetType().GetProperties()
.Where(x => !x.CustomAttributes.Any(y => y.AttributeType.Name == PropertyCopyIgnoreAttribute.Name) && x.CanRead && x.CanWrite && !x.GetGetMethod().IsVirtual);
var sourceProperties = source.GetType().GetProperties()
.Where(x => !x.CustomAttributes.Any(y => y.AttributeType.Name == PropertyCopyIgnoreAttribute.Name) && x.CanRead && x.CanWrite && !x.GetGetMethod().IsVirtual);
var copyProperties = sourceProperties.Join(destProperties, x => x.Name, y => y.Name, (x, y) => x);
foreach (var sourceProperty in copyProperties)
{
var prop = destProperties.FirstOrDefault(x => x.Name == sourceProperty.Name);
prop.SetValue(destination, sourceProperty.GetValue(source));
}
}
}