我有一个MVC3应用程序,需要将视图模型与数据库模型同步。我发现自己编写了太多的代码来在不同的对象之间复制属性。我尽可能避免这种情况,只需对数据模型进行子类化即可,但有时候发现这种做法过于受限。
我开发了一些扩展方法Object来支持浅层克隆具有相似名称的属性,并且效果非常好。然而,我想知道是否有更有效的方法来实现相同的功能。因此,我认为这是请求同行审查并提供改进此代码的选项。
更新: 我发现最好明确处理相关表格。测试IsVirtual可以防止关系在克隆期间被意外影响。请参见更新的CloneMatching方法。其他方法明确说明要更新或排除哪些属性。
这是一个示例,展示了如何将视图模型映射到数据模型:
```
我开发了一些扩展方法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"});