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

标签 c# asp.net-mvc

假设我有一个对象

class MyItem
{
     public string Name {get; set;}
     public string Description {get; set;}
}

我想创建一个ViewModel

class MyItemViewModel
{
     public string Name {get; set;}
     public string Description {get; set;}
     public string Username {get; set;}
}

我想在 Controller 上获取一个 MyItem 类型的对象并自动填充 ViewModel。使用 MyItem 中包含的值(即,如果它有一个名为 Name 的属性,则自动填写它)。

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

是否有一种干净的编程方式可以在对象之间复制具有相同名称和类型的属性,或者我是否需要手动完成?

最佳答案

你可以使用 AutoMapper为了这个任务。我在所有项目中都使用它在我的域模型和 View 模型之间进行映射。

您只需在 Application_Start 中定义一个映射:

Mapper.CreateMap<MyItem, MyItemViewModel>();

然后执行映射:

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

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

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

这使您的 Controller 操作非常简单。

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");
}

例如,假设您有一个包含用户名、密码和 IsAdmin 等属性的用户域模型,并且您有一个允许用户更改其用户名和密码但绝对不能更改 IsAdmin 属性的表单。因此,您将拥有一个包含绑定(bind)到 View 中 html 表单的用户名和密码属性的 View 模型,使用此技术您将只更新这 2 个属性,而 IsAdmin 属性保持不变。

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

Mapper.CreateMap<MyItem, MyItemViewModel>();

在集合之间映射时不需要做任何特殊的事情:

IEnumerable<MyItem> items = ...
IEnumerable<MyItemViewModel> vms = Mapper.Map<IEnumerable<MyItem>, IEnumerable<MyItemViewModel>>(items);

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

Install-Package AutoMapper

关于c# - 复制不同类型对象的最简单方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11970567/

相关文章:

c# - vshost.exe 一直在访问我的 .dll,我在构建它时无法更新它

C# 进程的实时标准输出/错误捕获

c# - MVcHtmlString 中的堆栈溢出异常

javascript - 使用 .net 渲染 React JS 服务器端

c# - 从代码后面输出Javascript时如何处理换行符

c# - 按计算属性搜索对象列表

c# - 如何在字典中存储任意数量的任意类型的数组

c# - 如何在使用 asp.net Identity 关闭浏览器后保留登录信息?

asp.net-mvc - 当用户在 mvc 上单击提交按钮时禁用它

c# - 上传文件时生成错误消息 ASP.NET