C# .NET - C# Class Reflection of user defined types

Asked By Corey on 24-May-13 10:09 AM
public class CustomerOptions
{
  [DefaultValue(false)]
  public bool ShowAccountData { get; set; }
 
  [DefaultValue(false)]
  public bool ShowLoanData { get; set; }
 
  [DefaultValue(false)]
  public bool ShowStatusData { get; set; }
 
}
 
public class Customer
{
  public string FirstName { get; set; }
 
  public string LastName { get; set; }
 
  public string SSN { get; set; }
 
  public CustomerOptions Options { get; set; }
 
} I have a utility that copy's our internal class values to a web service api's proxy classes. Using an attribute on our internal classes that has a mapping name to the proxy classes using reflection. For instance we want our SSN property to be "GovernmentIdentifier" and their's is "CustSSN". I add a property attribute to our internal classes for GovernmentIdentifier like so [TDCProperty("CustSSN")]. The copy utility will know that this value belongs to the proxy class property of "CustSSN". All this works, even for base classes except for a custom type property or reference type. In the above Customer class the Options property will not cast to the proxy api. A co worker said it is because not actually a property and cannot use PropertyInfo, GetProperty and these instances will need handled a different way. Below is the copy utility.
public static class CopyUtility {
     
    public enum TDCType {
      Customer,
      Login
    }
 
    public static void CopyObject(object source, out object tdcDestination, TDCType type)
    {
 
      tdcDestination = type == TDCType.Customer ? new TDCCustomerClass() : null;
 
      TDCPropertyAttribute tdcAttrib;
 
      //foreach property in source
      foreach (PropertyInfo sourcePropertyInfo in source.GetType().GetProperties()) {
 
         
 
        //is there a getter
        if (sourcePropertyInfo.CanRead) {
 
          //foreach custom attribute
          foreach (Attribute attr in sourcePropertyInfo.GetCustomAttributes(true)) {
            //try and cast to aatrib
            tdcAttrib = attr as TDCPropertyAttribute;
 
            //did we have a TDCPropertyAttribute?
            if (null != tdcAttrib) {
               
              PropertyInfo destinationProperty = tdcDestination.GetType().GetProperty(tdcAttrib.PropertyName);
              if (destinationProperty.CanWrite) {
                object value = sourcePropertyInfo.GetValue(source, null);
 
 
                destinationProperty.SetValue(tdcDestination, value, null);
 
                }
 
              Console.WriteLine("PropertyName = {0}",  tdcAttrib.PropertyName);
            }
 
          }
 
        }
 
      }
       
    }
  }
Robbe Morris replied to Corey on 24-May-13 10:18 AM
Your co-worker is right.  You'd have to call your copy method again on the instance of Options (CustomerOptions type).

All of that said, you'll want to hold the result from GetProperties() in a static variable.  This method call is slow.  Doing it on every call knowing that it will always return the same results is not a good idea. I ended up creating an object[] array to hold the properties and custom attributes derived from the first reflection call for GetProperties and GetCustomAttributes on a given type.  Then, hold those results in a static variable for that class type (in your case, Customer) and avoid subsequent reflection calls.

If you don't implement something like this, the performance of your app will suffer significantly.
Corey replied to Robbe Morris on 24-May-13 11:33 AM
Thanks Rob, could you please provide a solution?  I cannot wrap my head around a solution. :(

Robbe Morris replied to Corey on 24-May-13 12:27 PM
http://www.nullskull.com/a/719/net-reflection--copy-class-properties.aspx
Corey replied to Robbe Morris on 24-May-13 02:09 PM
Rob, the solution in the link is not working.  The proxy api class xCustomerOptions is not being copied from the CustomerOptions class on the Customer.

Error: Object of type 'TestAttributeReflectionUtility.TDCProxyCustomerOptionsClass' cannot be converted to type 'TestAttributeReflectionUtility.TDCCustomerOptionsClass'.