Note that there are some explanatory texts on larger screens.

plurals
  1. POBest way to clone properties of disparate objects
    primarykey
    data
    text
    <p>I have an MVC3 application that needs to sync view models with database models. I found myself writing way too much code to copy properties back and forth between the different objects. I avoided this where I could simply subclass the data model, but at other times, I found that too restricting.</p> <p>I developed a few extension methods on Object to support shallow cloning of properties with similar names, and this has worked rather well. However, I'm wondering if there is a more efficient means to accomplish the same thing. So I guess this is asking for peer review and options to improve upon this code.</p> <p>UPDATE: I've found it better to handle related tables explicitly. Testing for IsVirtual will prevent relations from being inadvertently affected during cloning. See updated CloneMatching method. The others explicitly state which properties to update or exclude.</p> <pre><code>public static class CustomExtensions { public static T CloneMatching&lt;T, S&gt;(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 &amp;&amp; tPI.PropertyType.IsAssignableFrom(sPI.PropertyType) &amp;&amp; !tPI.PropertyType.IsVirtual) { tPI.SetValue(target, sPI.GetValue(source, null), null); } } return target; } public static T CloneProperties&lt;T, S&gt;(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 &amp;&amp; tPI.PropertyType.IsAssignableFrom(sPI.PropertyType)) { tPI.SetValue(target, sPI.GetValue(source, null), null); } } } return target; } public static T CloneExcept&lt;T, S&gt;(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 &amp;&amp; tPI.PropertyType.IsAssignableFrom(sPI.PropertyType)) { tPI.SetValue(target, sPI.GetValue(source, null), null); } } } return target; } } </code></pre> <p>Here is an example of how I use it to map a view model to the data model.</p> <pre><code>DataSession.Quote.CloneProperties(viewModel, new[] {"PaymentType","CardHolder","CardHolderZip","CardNumber","CardExp","CVC", "AccountHolder","AccountHolderZip","ABA","Account", "AccuracyAgreement","PrivacyTermsAgreement","ElectronicSignatureAgreement"}); </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload