简体   繁体   English

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

[英]C# Reflection - merge two objects together

I have a need to update object A's property if null with that from object B's equivalent property if that is not null. 我需要用对象B的等效属性(如果不为null)更新对象A的属性(如果为null)。 I wanted code I can use for various objects. 我想要可以用于各种对象的代码。

I had a version working until one of the objects contained a propert of type List, which is where I have a blank in the code below. 我有一个版本可以工作,直到其中一个对象包含List类型的属性,在下面的代码中空白。 My main question is how can I best implement this part of the code. 我的主要问题是如何最好地实现这部分代码。 Secondly is there a better way of doing this whole thing and thirdly I know its never going to be rapid but any suggestions to speed it up would be appreciated. 其次,有一种更好的方法来完成这件事,其三,我知道它永远不会很快,但是任何加快它的建议都会受到赞赏。

Thanks in advance. 提前致谢。

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

I have created the below extension method for use in my latest project and it works fine, collections and all. 我创建了以下扩展方法以在我的最新项目中使用,并且可以正常工作,收集所有内容。 It is a pretty much a simpler version of what you are doing in your method. 这是您在方法中所做的工作的一个非常简单的版本。 With mine both classes have to be the same type. 对于我的,两个类必须是同一类型。 What problem do you encounter with collections? 您在收藏中遇到什么问题?

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

Hi I modified Ben Robinsons solution in order to not overwrite Collections or list, instead, it adds the elements of one object to the other one where the merging is happening: 嗨,我修改了Ben Robinsons解决方案,以不覆盖Collections或list,而是将一个对象的元素添加到发生合并的另一个对象中:

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

        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM