克隆不同对象属性的最佳方法

我有一个MVC3应用程序需要将视图模型与数据库模型同步。 我发现自己写了太多代码来在不同对象之间来回复制属性。 我避免了这种情况,我可以简单地对数据模型进行子类化,但在其他时候,我发现它太过限制了。

我在Object上开发了一些扩展方法,以支持具有相似名称的属性的浅层克隆,并且这种方法运行得相当好。 但是,我想知道是否有更有效的方法来完成同样的事情。 所以我想这是要求同行评审和选项来改进这个代码。

更新:我发现明确处理相关表格更好。 对IsVirtual进行测试可以防止在克隆过程中无意中影响关系。 请参阅更新的CloneMatching方法。 其他人明确说明要更新或排除的属性。

public static class CustomExtensions { public static T CloneMatching(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(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(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"});