【发布时间】:2010-12-19 09:31:54
【问题描述】:
更新:这些东西已经演变成一个不错的项目,请参阅http://valueinjecter.codeplex.com
看看这个,我刚刚写了一个简单的自动映射器,它从一个对象具有相同名称和类型的属性中获取值并将其放入另一个对象中,您可以为您可能需要的每种类型添加异常(ifs、switch)
那么告诉我你怎么看?
我这样做是为了做这样的事情:
Product –> ProductDTO
ProductDTO –> Product
就这样开始了:
我在 Inputs/Dto/ViewModels 中为 DropDowns 使用“对象”类型,因为我向 html 发送了一个 IEnumerable
public void Map(object a, object b)
{
var pp = a.GetType().GetProperties();
foreach (var pa in pp)
{
var value = pa.GetValue(a, null);
// property with the same name in b
var pb = b.GetType().GetProperty(pa.Name);
if (pb == null)
{
//no such property in b
continue;
}
if (pa.PropertyType == pb.PropertyType)
{
pb.SetValue(b, value, null);
}
}
}
更新:
实际用法:
构建方法(输入 = Dto):
public static TI BuildInput<TI, T>(this T entity) where TI: class, new()
{
var input = new TI();
input = Map(entity, input) as TI;
return input;
}
public static T BuildEntity<T, TI, TR>(this TI input)
where T : class, new()
where TR : IBaseAdvanceService<T>
{
var id = (long)input.GetType().GetProperty("Id").GetValue(input, null);
var entity = LocatorConfigurator.Resolve<TR>().Get(id) ?? new T();
entity = Map(input, entity) as T;
return entity;
}
public static TI RebuildInput<T, TI, TR>(this TI input)
where T: class, new()
where TR : IBaseAdvanceService<T>
where TI : class, new()
{
return input.BuildEntity<T, TI, TR>().BuildInput<TI, T>();
}
在控制器中:
public ActionResult Create()
{
return View(new Organisation().BuildInput<OrganisationInput, Organisation>());
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(OrganisationInput o)
{
if (!ModelState.IsValid)
{
return View(o.RebuildInput<Organisation,OrganisationInput, IOrganisationService>());
}
organisationService.SaveOrUpdate(o.BuildEntity<Organisation, OrganisationInput, IOrganisationService>());
return RedirectToAction("Index");
}
真正的Map方法
public static object Map(object a, object b)
{
var lookups = GetLookups();
var propertyInfos = a.GetType().GetProperties();
foreach (var pa in propertyInfos)
{
var value = pa.GetValue(a, null);
// property with the same name in b
var pb = b.GetType().GetProperty(pa.Name);
if (pb == null)
{
continue;
}
if (pa.PropertyType == pb.PropertyType)
{
pb.SetValue(b, value, null);
}
else if (lookups.Contains(pa.Name) && pa.PropertyType == typeof(LookupItem))
{
pb.SetValue(b, (pa.GetValue(a, null) as LookupItem).GetSelectList(pa.Name), null);
}
else if (lookups.Contains(pa.Name) && pa.PropertyType == typeof(object))
{
pb.SetValue(b, pa.GetValue(a, null).ReadSelectItemValue(), null);
}
else if (pa.PropertyType == typeof(long) && pb.PropertyType == typeof(Organisation))
{
pb.SetValue(b, pa.GetValue<long>(a).ReadOrganisationId(), null);
}
else if (pa.PropertyType == typeof(Organisation) && pb.PropertyType == typeof(long))
{
pb.SetValue(b, pa.GetValue<Organisation>(a).Id, null);
}
}
return b;
}
【问题讨论】:
-
离题——我喜欢你对“问题”的开场白:“看看这个……”!哈哈。我想过这样做,但没有球
-
@cottsak 是的,开场真的很好 :D,从没见过这样的
-
@ChuckNorris - 您能否指出为什么不建议将 Automapper(最初)用于 ViewModel模型映射?我意识到这是本次讨论中的一个非常晚的评论,许多事情可能在 Automapper 和 ValueInjector 中都取得了进展,但尽管如此,如果您对为什么要避免使用 Automapper 有一些值得注意的观点,请告诉我们。
-
@FairDune 我这样做了 ^ 因为我的类很简单,我认为不需要为每一对编写配置,一个简单的约定就可以了
-
@ChuckNorris 谢谢。我同意。在为 ValueInjecter 帖子搜索 SO 之后,我得到了很多答案。我现在正在使用 ValueInjecter。
标签: c# asp.net-mvc mapping automapper automapping