复制不同类型对象的最简单方法

Joh*_*ell 2 c# asp.net-mvc

所以我想说我有一个对象

class MyItem
{
     public string Name {get; set;}
     public string Description {get; set;}
}
Run Code Online (Sandbox Code Playgroud)

我想创建一个ViewModel

class MyItemViewModel
{
     public string Name {get; set;}
     public string Description {get; set;}
     public string Username {get; set;}
}
Run Code Online (Sandbox Code Playgroud)

我想在控制器上获取MyItem类型的对象并自动填充ViewModel.使用MyItem中包含的值(即,如果它具有名为Name的属性,则自动填充它).

我想避免的是Model.Name = Item.Name行列表.MyItemViewModel也将具有不同的属性和显示值,因此我不能简单地在视图模型中嵌入MyItem.

是否有一种干净的程序化方法来复制对象之间相同名称和类型的属性,或者我是不是手工操作?

Dar*_*rov 5

您可以使用AutoMapper执行此任务.我在所有项目中使用它来映射我的域模型和视图模型.

您只需在以下位置定义映射Application_Start:

Mapper.CreateMap<MyItem, MyItemViewModel>();
Run Code Online (Sandbox Code Playgroud)

然后执行映射:

public ActionResult Index()
{
    MyItem item = ... fetch your domain model from a repository
    MyItemViewModel vm = Mapper.Map<MyItem, MyItemViewModel>(item);
    return View(vm);
}
Run Code Online (Sandbox Code Playgroud)

您可以编写一个自定义操作过滤器来覆盖OnActionExecuted方法,并使用相应的视图模型替换传递给视图的模型:

[AutoMap(typeof(MyItem), typeof(MyItemViewModel))]
public ActionResult Index()
{
    MyItem item = ... fetch your domain model from a repository
    return View(item);
}
Run Code Online (Sandbox Code Playgroud)

这使您的控制器操作非常简单.

AutoMapper还有另一个非常有用的方法,当你想要更新一些东西时,它可以在你的POST动作中使用:

[HttpPost]
public ActionResult Edit(MyItemViewModel vm)
{
    // Get the domain model that we want to update
    MyItem item = Repository.GetItem(vm.Id);

    // Merge the properties of the domain model from the view model =>
    // update only those that were present in the view model
    Mapper.Map<MyItemViewModel, MyItem>(vm, item);

    // At this stage the item instance contains update properties
    // for those that were present in the view model and all other
    // stay untouched. Now we could persist the changes
    Repository.Update(item);

    return RedirectToAction("Success");
}
Run Code Online (Sandbox Code Playgroud)

想象一下,例如,您有一个包含用户名,密码和IsAdmin等属性的用户域模型,并且您有一个允许用户更改其用户名和密码但绝对不更改IsAdmin属性的表单.因此,您将拥有一个视图模型,其中包含绑定到视图中html表单的Username和Password属性,并且使用此技术,您将只更新这两个属性,保持IsAdmin属性不变.

AutoMapper也适用于集合.一旦定义了简单类型之间的映射:

Mapper.CreateMap<MyItem, MyItemViewModel>();
Run Code Online (Sandbox Code Playgroud)

在集合之间进行映射时,您不需要做任何特殊操作:

IEnumerable<MyItem> items = ...
IEnumerable<MyItemViewModel> vms = Mapper.Map<IEnumerable<MyItem>, IEnumerable<MyItemViewModel>>(items);
Run Code Online (Sandbox Code Playgroud)

所以不要再等了,在NuGet控制台中键入以下命令并欣赏节目:

Install-Package AutoMapper
Run Code Online (Sandbox Code Playgroud)