2012-03-28 39 views
1

上運行時鑄造我有以下代碼複製屬性值從一個對象到另一個對象通過匹配他們的屬性名稱:使用隱式CON版本

public static void CopyProperties(object source, object target,bool caseSenstive=true) 
    { 
     PropertyInfo[] targetProperties = target.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance); 
     PropertyInfo[] sourceProperties = source.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance); 
     foreach (PropertyInfo tp in targetProperties) 
     { 
      var sourceProperty = sourceProperties.FirstOrDefault(p => p.Name == tp.Name); 
      if (sourceProperty == null && !caseSenstive) 
      { 
       sourceProperty = sourceProperties.FirstOrDefault(p => p.Name.ToUpper() == tp.Name.ToUpper()); 
      } 
      // If source doesn't have this property, go for next one. 
      if(sourceProperty ==null) 
      { 
       continue; 
      } 

      // If target property is not writable then we can not set it; 
      // If source property is not readable then cannot check it's value 
      if (!tp.CanWrite || !sourceProperty.CanRead) 
      { 
       continue; 
      } 

      MethodInfo mget = sourceProperty.GetGetMethod(false); 
      MethodInfo mset = tp.GetSetMethod(false); 

      // Get and set methods have to be public 
      if (mget == null) 
      { 
       continue; 
      } 

      if (mset == null) 
      { 
       continue; 
      } 


      var sourcevalue = sourceProperty.GetValue(source, null); 
      tp.SetValue(target, sourcevalue, null); 

     } 
    } 

這是工作以及當目標屬性的類型和來源是一樣的。但是當需要投射時,代碼不起作用。

例如,我有以下對象:

class MyDateTime 
{ 
    public static implicit operator DateTime?(MyDateTime myDateTime) 
    { 
     return myDateTime.DateTime; 
    } 

    public static implicit operator DateTime(MyDateTime myDateTime) 
    { 
     if (myDateTime.DateTime.HasValue) 
     { 
      return myDateTime.DateTime.Value; 
     } 
     else 
     { 
      return System.DateTime.MinValue; 
     } 
    } 

    public static implicit operator MyDateTime(DateTime? dateTime) 
    { 
     return FromDateTime(dateTime); 
    } 

    public static implicit operator MyDateTime(DateTime dateTime) 
    { 
     return FromDateTime(dateTime); 
    } 
} 

如果我這樣做,則隱式轉換被調用,一切正常:

MyDateTime x= DateTime.Now; 

但是,當我有兩個對象其中一個具有DateTime,另一個具有MyDateTime,並且我使用上述代碼將屬性從一個對象複製到另一個對象,但不會生成錯誤,表示DateTime無法轉換爲MyTimeDate。

我該如何解決這個問題?

+0

五言中不是一般的情況下,但也許它可以幫助你: http://stackoverflow.com/questions/4501469/c-sharp-implicit-cast-overloading-and-reflection-problem – dvvrd 2012-03-28 16:50:58

回答

1

一個可怕的做法,應該工作是混合dynamic與反思:

private static T ConvertValue<T>(dynamic value) 
{ 
    return value; // This will perform conversion automatically 
} 

然後:

var sourceValue = sourceProperty.GetValue(source, null); 
if (sourceProperty.PropertyType != tp.PropertyType) 
{ 
    var method = typeof(PropertyCopier).GetMethod("ConvertValue", 
     BindingFlags.Static | BindingFlags.NonPublic); 
    method = method.MakeGenericMethod(new[] { tp.PropertyType }; 
    sourceValue = method.Invoke(null, new[] { sourceValue }); 
} 
tp.SetValue(target, sourceValue, null); 

我們需要使用反射用正確的類型參數來調用泛型方法,但動態輸入將爲您使用正確的轉換運算符。

哦,還有一個最後的要求:請不要在我的名字附近加上我的名字附近的這段代碼,無論是在註釋,提交日誌。 AARGH。

+0

它的工作原理,但爲什麼不把你的名字放在這個代碼的附近? – mans 2012-03-29 16:14:10

+0

@ user654019:在進行反射*或*動態輸入時,我非常緊張。把它們放在一起對我來說太過分了:)(更嚴重的是,它完全取決於上下文,如果失敗會發生什麼?它是否處於一個環境中,無論如何都能很好地控制這些屬性? ) – 2012-03-29 16:17:41

+0

是的,我想用它在MVC應用程序中複製實體對象和模型對象之間的屬性。所以這些財產是衆所周知的。 – mans 2012-03-29 17:53:06