C#Reflection - 将两个对象合并在一起

时间:2010-07-29 09:48:29

标签: c#

我需要更新对象A的属性,如果null为对象B的等效属性,如果它不为null。我想要可以用于各种对象的代码。

我有一个版本工作,直到其中一个对象包含List类型的属性,这是我在下面的代码中有空白的地方。我的主要问题是如何才能最好地实现这部分代码。其次是有更好的方法来做这件事,第三,我知道它永远不会很快,但任何加快它的建议都会受到赞赏。

提前致谢。

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");
    }

2 个答案:

答案 0 :(得分: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;
        }
    }

答案 1 :(得分:0)

您好我修改了Ben Robinsons解决方案,以便不覆盖集合或列表,而是将一个对象的元素添加到正在进行合并的另一个对象:

 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);
            }

        }
    }
}