2010-07-29 77 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); 
      } 

     } 
    } 
}