我有一个MVC3应用程序需要将视图模型与数据库模型同步。我发现自己编写了太多代码来在不同对象之间来回复制属性。我避免了这种情况,我可以简单地对数据模型进行子类化,但在其他时候,我发现它太受限制了。
我在Object上开发了一些扩展方法,以支持具有相似名称的属性的浅层克隆,并且这种方法运行得相当好。但是,我想知道是否有更有效的方法来完成同样的事情。所以我想这是要求同行评审和选项来改进这段代码。
更新: 我发现明确处理相关表会更好。对IsVirtual进行测试可以防止在克隆过程中无意中影响关系。请参阅更新的CloneMatching方法。其他人明确说明要更新或排除的属性。
public static class CustomExtensions
{
public static T CloneMatching<T, S>(this T target, S source)
where T : class
where S : class
{
if (source == null)
{
return target;
}
Type sourceType = typeof(S);
Type targetType = typeof(T);
BindingFlags flags = BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance;
PropertyInfo[] properties = sourceType.GetProperties();
foreach (PropertyInfo sPI in properties)
{
PropertyInfo tPI = targetType.GetProperty(sPI.Name,flags);
if (tPI != null && tPI.PropertyType.IsAssignableFrom(sPI.PropertyType) && !tPI.PropertyType.IsVirtual)
{
tPI.SetValue(target, sPI.GetValue(source, null), null);
}
}
return target;
}
public static T CloneProperties<T, S>(this T target, S source, string[] propertyNames)
where T : class
where S : class
{
if (source == null)
{
return target;
}
Type sourceType = typeof(S);
Type targetType = typeof(T);
BindingFlags flags = BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance;
PropertyInfo[] properties = sourceType.GetProperties();
foreach (PropertyInfo sPI in properties)
{
if (propertyNames.Contains(sPI.Name))
{
PropertyInfo tPI = targetType.GetProperty(sPI.Name, flags);
if (tPI != null && tPI.PropertyType.IsAssignableFrom(sPI.PropertyType))
{
tPI.SetValue(target, sPI.GetValue(source, null), null);
}
}
}
return target;
}
public static T CloneExcept<T, S>(this T target, S source, string[] propertyNames)
where T : class
where S : class
{
if (source == null)
{
return target;
}
Type sourceType = typeof(S);
Type targetType = typeof(T);
BindingFlags flags = BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance;
PropertyInfo[] properties = sourceType.GetProperties();
foreach (PropertyInfo sPI in properties)
{
if (!propertyNames.Contains(sPI.Name))
{
PropertyInfo tPI = targetType.GetProperty(sPI.Name, flags);
if (tPI != null && tPI.PropertyType.IsAssignableFrom(sPI.PropertyType))
{
tPI.SetValue(target, sPI.GetValue(source, null), null);
}
}
}
return target;
}
}
以下是我如何使用它将视图模型映射到数据模型的示例。
DataSession.Quote.CloneProperties(viewModel,
new[] {"PaymentType","CardHolder","CardHolderZip","CardNumber","CardExp","CVC",
"AccountHolder","AccountHolderZip","ABA","Account",
"AccuracyAgreement","PrivacyTermsAgreement","ElectronicSignatureAgreement"});
答案 0 :(得分:1)
您可以考虑使用Object.MemberwiseClone
方法。
MemberwiseClone
方法通过创建新对象,然后将当前对象的非静态字段复制到新对象来创建浅表副本。 (docs.microsoft)
该方法受保护。这意味着您必须在类中实现Clone
方法。为了使事情变得更加有趣,您还可以在课程中添加ICloneable
。
class MyClass: ICloneable
{
// all your code
MyClass Clone()
{
return (MyClass)this.MemberwiseClone();
}
}