C# 复制不同类型对象的最简单方法
假设我有一个对象C# 复制不同类型对象的最简单方法,c#,asp.net-mvc,C#,Asp.net Mvc,假设我有一个对象 class MyItem { public string Name {get; set;} public string Description {get; set;} } 我想创建一个视图模型 class MyItemViewModel { public string Name {get; set;} public string Description {get; set;} public string Username {g
class MyItem
{
public string Name {get; set;}
public string Description {get; set;}
}
我想创建一个视图模型
class MyItemViewModel
{
public string Name {get; set;}
public string Description {get; set;}
public string Username {get; set;}
}
我想在控制器上获取MyItem类型的对象,并自动填充ViewModel。使用MyItem中包含的值(即,如果它有一个名为Name的属性,则自动填写)
我试图避免的是Model.Name=Item.Name
行的列表。MyItemViewModel还将具有不同的属性和显示值,因此我不能简单地将MyItem嵌入视图模型中
是否有一种干净的编程方法可以在对象之间复制相同名称和类型的属性,还是我只能手工复制 您可以使用此任务。我在所有项目中都使用它来映射我的域模型和视图模型
只需在应用程序\u Start
中定义映射即可:
Mapper.CreateMap<MyItem, MyItemViewModel>();
这使得控制器的操作非常简单
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");
}
您可能需要进行反思才能做到这一点 下面是一个例子 全部:
//
///将“from”对象的所有属性复制到此对象(如果存在)。
///
///在其中复制特性的对象
///用作源的对象
///从副本中排除这些属性
公共静态void copyProperties from
(此对象到,对象从,字符串[]不包括属性)
{
键入targetType=to.GetType();
类型sourceType=from.GetType();
PropertyInfo[]sourceProps=sourceType.GetProperties();
foreach(sourceProps中的var propInfo)
{
//过滤属性
如果(不包括数据属性!=null
&&excludedProperties.Contains(propInfo.Name))
继续;
//从目标获取匹配的属性
toProp的属性信息=
(targetType==sourceType)?propInfo:targetType.GetProperty(propInfo.Name);
//如果它存在并且是可写的
if(toProp!=null&&toProp.CanWrite)
{
//将值从源复制到目标
对象值=propInfo.GetValue(from,null);
toProp.SetValue(to,value,null);
}
}
}
如果您想从头做起,一些反射代码可以在这里帮助您。性能不太好,但肯定很容易建立和维护。检查本手册中提供的方法
您可以使用“Type.GetProperties”获取目标对象上的属性列表
获取公共属性的示例:
PropertyInfo[] myPropertyInfo = myType.GetProperties(BindingFlags.Public|BindingFlags.Instance);
请参阅AutoMapper:我不明白为什么不能在模型中创建MyItem类型的属性,并将特定的自定义模型字段(属性/显示值)添加为依赖MyItem属性的模型上的新属性?如果可能的话,这将是一个很好的解决方案。
[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");
}
Mapper.CreateMap<MyItem, MyItemViewModel>();
IEnumerable<MyItem> items = ...
IEnumerable<MyItemViewModel> vms = Mapper.Map<IEnumerable<MyItem>, IEnumerable<MyItemViewModel>>(items);
Install-Package AutoMapper
/// <summary>
/// Copies all the properties of the "from" object to this object if they exist.
/// </summary>
/// <param name="to">The object in which the properties are copied</param>
/// <param name="from">The object which is used as a source</param>
/// <param name="excludedProperties">Exclude these properties from the copy</param>
public static void copyPropertiesFrom
(this object to, object from, string[] excludedProperties)
{
Type targetType = to.GetType();
Type sourceType = from.GetType();
PropertyInfo[] sourceProps = sourceType.GetProperties();
foreach (var propInfo in sourceProps)
{
//filter the properties
if (excludedProperties != null
&& excludedProperties.Contains(propInfo.Name))
continue;
//Get the matching property from the target
PropertyInfo toProp =
(targetType == sourceType) ? propInfo : targetType.GetProperty(propInfo.Name);
//If it exists and it's writeable
if (toProp != null && toProp.CanWrite)
{
//Copy the value from the source to the target
Object value = propInfo.GetValue(from, null);
toProp.SetValue(to,value , null);
}
}
}
PropertyInfo[] myPropertyInfo = myType.GetProperties(BindingFlags.Public|BindingFlags.Instance);