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

C#反射-将两个对象合并在一起,c#,C#,如果对象a的属性为null,我需要将其更新为对象B的等效属性(如果该属性不为null)。我想要可以用于各种对象的代码 我有一个版本一直在工作,直到其中一个对象包含一个类型为List的propert,这就是我在下面的代码中有一个空白的地方。我的主要问题是如何最好地实现这部分代码。第二,有没有更好的方法来完成这整个事情,第三,我知道它永远不会很快,但任何建议,以加快它将不胜感激 提前谢谢 public T MergeWith<T, U>(T primarySource, U second

如果对象a的属性为null,我需要将其更新为对象B的等效属性(如果该属性不为null)。我想要可以用于各种对象的代码

我有一个版本一直在工作,直到其中一个对象包含一个类型为List的propert,这就是我在下面的代码中有一个空白的地方。我的主要问题是如何最好地实现这部分代码。第二,有没有更好的方法来完成这整个事情,第三,我知道它永远不会很快,但任何建议,以加快它将不胜感激

提前谢谢

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");
    }
public T MergeWith(T primarySource,U secondarySource),其中U:class,T
{
类型primaryType=类型(T);
类型secondaryType=类型(U);
foreach(primaryType.GetProperties()中的PropertyInfo primaryInfo)
{
if(primaryInfo.CanWrite)
{
对象currentPrimary=primaryInfo.GetValue(primarySource,null);
PropertyInfo secondaryInfo=secondaryType.GetProperty(primaryInfo.Name);
object currentSecondary=secondaryInfo.GetValue(secondarySource,null);
如果(currentPrimary==null&¤tSecondary!=null)
{
primaryInfo.SetValue(primarySource,currentSecondary,null);
}
else if((currentPrimary!=null&¤tSecondary!=null)&&isChildClass(primaryInfo))
{
if(isCollection(currentPrimary))
{
//这里
}
其他的
{
MethodInfo method=typeof(NavigationModel).GetMethod(“合并”);
MethodInfo generic=method.MakeGenericMethod(primaryInfo.PropertyType,primaryInfo.PropertyType);
object returnChild=generic.Invoke(这个,新对象[2]{currentPrimary,currentSecondary});
}
}
}
}
返回主源;
}
私有布尔isCollection(对象属性)
{
返回typeof(ICollection).IsAssignableFrom(property.GetType())
||typeof(ICollection).IsAssignableFrom(property.GetType());
}
私有bool是ChildClass(PropertyInfo PropertyInfo)
{
返回(propertyInfo.PropertyType.IsClass&!propertyInfo.PropertyType.IsValueType&&
!propertyInfo.PropertyType.IsPrimitive&&propertyInfo.PropertyType.FullName!=“System.String”);
}

我已经创建了下面的扩展方法,用于我的最新项目,它可以很好地工作,无论是集合还是其他。它是您在方法中所做工作的一个非常简单的版本。我的两个类必须是同一类型。您在收集时遇到了什么问题

    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;
        }
    }
公共静态类扩展方法
{
公共静态tenty CopyTo(此tenty OriginalEntity,tenty 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);
}
}
回归本源性;
}
}

Hi I修改了Ben Robinson解决方案,以避免覆盖集合或列表,相反,它将一个对象的元素添加到发生合并的另一个对象中:

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

        }
    }
}
公共静态类扩展方法
{
公共静态tenty CopyTo(此tenty OriginalEntity,tenty EntityToMergeOn)
{
PropertyInfo[]oProperties=OriginalEntity.GetType().GetProperties();
foreach(PropertyInfo-CurrentProperty in-oProperties.Where(p=>p.CanWrite))
{
var originalValue=CurrentProperty.GetValue(EntityToMergeOn);
if(originalValue!=null)
{
IListLogic(原始属性、当前属性、原始值);
}
其他的
{
var value=CurrentProperty.GetValue(原始属性,null);
CurrentProperty.SetValue(EntityToMergeOn,value,null);
}
}
回归本源性;
}
私有静态无效IListLogic(TEntity OriginalEntity、PropertyInfo CurrentProperty、object originalValue)
{
if(原始值为IList)
{
var templast=(初始值为IList);
var existingList=CurrentProperty.GetValue(OriginalEntity)作为IList;
foreach(模板列表中的变量项)
{
现有列表。添加(项);
}
}
}
}

问题出在哪里?我最近创建了一个扩展方法,它的功能非常类似,只要属性是可写的,就可以处理集合。看起来他的解决方案将数据从一种类型复制到另一种类型。您需要扩展您的答案以获取类型参数,并定义如何确定类型之间哪些属性是等效的。是的,我知道这一点,我理解我的代码的功能,但是您指出的差异与所述问题无关,即我如何处理集合。这是一个可以很好地处理集合的示例,更重要的是,它演示了一个事实,即作为集合的属性不需要与其他类型的属性区别对待。我需要遍历列表中的每个对象,执行另一个递归调用(如果两者都不为null),以再次设置其属性。如果项目在第二个对象(但不是主对象)的列表中,则添加它。我想。