2010-07-29 25 views
2

我有需要更新對象A的屬性,如果null與來自對象B的等價屬性,如果它不爲null。我想要我可以用於各種對象的代碼。C#反射 - 將兩個對象合併在一起

我有一個版本的工作,直到其中一個對象包含一個屬性類型列表,這是我在下面的代碼中有一個空白。我的主要問題是如何最好地實現這部分代碼。其次是有更好的方式來做這件事,第三我知道它永遠不會很快,但任何建議,以加快它將不勝感激。

在此先感謝。

public T MergeWith<T, U>(T primarySource, U secondarySource) where U : class, T 
    { 
     Type primaryType = typeof(T); 
     Type secondaryType = typeof(U); 
     foreach (PropertyInfo primaryInfo in primaryType.GetProperties()) 
     { 
      if (primaryInfo.CanWrite) 
      { 
       object currentPrimary = primaryInfo.GetValue(primarySource, null); 

       PropertyInfo secondaryInfo = secondaryType.GetProperty(primaryInfo.Name); 
       object currentSecondary = secondaryInfo.GetValue(secondarySource, null); 

       if (currentPrimary == null && currentSecondary != null) 
       { 
        primaryInfo.SetValue(primarySource, currentSecondary, null); 
       } 
       else if ((currentPrimary != null && currentSecondary != null) && isChildClass(primaryInfo)) 
       { 
        if (isCollection(currentPrimary)) 
        { 
         // here 


        } 
        else 
        { 
         MethodInfo method = typeof(NavigationModel).GetMethod("MergeWith"); 
         MethodInfo generic = method.MakeGenericMethod(primaryInfo.PropertyType, primaryInfo.PropertyType); 
         object returnChild = generic.Invoke(this, new object[2] { currentPrimary, currentSecondary }); 
        } 
       } 
      } 
     } 

     return primarySource; 
    } 

    private bool isCollection(object property) 
    { 
     return typeof(ICollection).IsAssignableFrom(property.GetType()) 
      || typeof(ICollection<>).IsAssignableFrom(property.GetType()); 
    } 


    private bool isChildClass(PropertyInfo propertyInfo) 
    { 
     return (propertyInfo.PropertyType.IsClass && !propertyInfo.PropertyType.IsValueType && 
          !propertyInfo.PropertyType.IsPrimitive && propertyInfo.PropertyType.FullName != "System.String"); 
    } 
+0

什麼問題,我最近創建了一個擴展方法,它做了非常相似的事情,只要該屬性是可寫的,它就可以正常工作。 – 2010-07-29 09:54:17

回答

7

我已經創建了一個使用下面的擴展方法在我最新的項目並能正常工作,集合所有。這是一個非常簡單的版本,你正在使用你的方法。與我的兩個類必須是相同的類型。你遇到什麼問題與收藏?

public static class ExtensionMethods 
    { 
     public static TEntity CopyTo<TEntity>(this TEntity OriginalEntity, TEntity NewEntity) 
     { 
      PropertyInfo[] oProperties = OriginalEntity.GetType().GetProperties(); 

      foreach (PropertyInfo CurrentProperty in oProperties.Where(p => p.CanWrite)) 
      { 
       if (CurrentProperty.GetValue(NewEntity, null) != null) 
       { 
        CurrentProperty.SetValue(OriginalEntity, CurrentProperty.GetValue(NewEntity, null), null); 
       } 
      } 

      return OriginalEntity; 
     } 
    } 
+0

看起來他的解決方案將數據從一種類型複製到另一種類型。您需要擴展您的答案以獲取類型類型參數,並定義如何確定哪些屬性在類型之間是等同的。 – 2010-07-29 10:03:23

+0

是的,我意識到這一點,我明白我的代碼是幹什麼的,但是你指出的不同之處並不在於說明問題,即我如何處理集合。這是一個與集合正常工作的例子,更重要的是,它證明了作爲集合的屬性不需要與其他類型的屬性區別對待的事實。 – 2010-07-29 10:13:10

+0

我需要遍歷列表中的每個對象執行另一個遞歸調用,如果兩個都不爲null,以便再次設置它的proprities。如果該項目在第二個對象的列表中(但不是主要對象),則添加它。我認爲。 – tjh7 2010-07-29 10:26:29

0

您好我修改本羅賓遜的解決方案,以不覆蓋集合或列表,相反,它增加了一個對象到另一個地方的合併正在發生的元素:

public static class ExtensionMethods 
{ 
    public static TEntity CopyTo<TEntity>(this TEntity OriginalEntity, TEntity EntityToMergeOn) 
    { 
     PropertyInfo[] oProperties = OriginalEntity.GetType().GetProperties(); 

     foreach (PropertyInfo CurrentProperty in oProperties.Where(p => p.CanWrite)) 
     { 
      var originalValue = CurrentProperty.GetValue(EntityToMergeOn); 

      if (originalValue != null) 
      { 
       IListLogic<TEntity>(OriginalEntity, CurrentProperty, originalValue); 
      } 
      else 
      { 
       var value = CurrentProperty.GetValue(OriginalEntity, null); 
       CurrentProperty.SetValue(EntityToMergeOn, value, null); 
      } 
     } 

     return OriginalEntity; 
    } 

    private static void IListLogic<TEntity>(TEntity OriginalEntity, PropertyInfo CurrentProperty, object originalValue) 
    { 
     if (originalValue is IList) 
     { 
      var tempList = (originalValue as IList); 
      var existingList = CurrentProperty.GetValue(OriginalEntity) as IList; 

      foreach (var item in tempList) 
      { 
       existingList.Add(item); 
      } 

     } 
    } 
}