.net 在C#中合并两个对象

s3fp2yjn  于 2023-02-06  发布在  .NET
关注(0)|答案(7)|浏览(343)

我有一个具有各种属性的对象模型MyObject,其中有两个MyObject示例:示例A和示例B。如果示例B具有非空值,我希望复制示例A中的属性并将其替换为示例B中的属性。
如果我只有一个类和3个属性,没有问题,我可以很容易地硬编码它(这是我开始做的),但我实际上有12个不同的对象模型,每个模型大约有10个属性。
有什么好办法呢?

plupiseo

plupiseo1#

更新如果需要大量调用此方法,请改用AutoMapper。自动Map器使用Reflection.Emit生成动态方法,比反射快得多。'

可以使用反射复制属性的值:

public void CopyValues<T>(T target, T source)
{
    Type t = typeof(T);

    var properties = t.GetProperties().Where(prop => prop.CanRead && prop.CanWrite);

    foreach (var prop in properties)
    {
        var value = prop.GetValue(source, null);
        if (value != null)
             prop.SetValue(target, value, null);
    }
}

我把它变成了泛型以确保类型安全,如果你想包含私有属性,你应该使用Type.GetProperties()的重写,指定绑定标志。

j0pj023g

j0pj023g2#

我已经尝试了凯尔芬利的Merge Two Objects into an Anonymous Type所描述的,它是完美的工作。
对于TypeMerger,合并非常简单,如下所示

var obj1 = new {foo = "foo"};

var obj2 = new {bar = "bar"};

var mergedObject = TypeMerger.MergeTypes(obj1 , obj2 );

就是这样!你得到了合并对象。除此之外,还有一个忽略特定属性的规定。你也可以在MVC 3中使用同样的方法。

w51jfk4q

w51jfk4q3#

您可以使用反射来实现这一点,但正如有人所说的那样,它会有性能损失。
由于您使用的是预期的类设计,因此可以通过使用如下扩展方法来实现相同的目标:

public static class MyClassExtensions
{
    public static void Merge(this MyClass instanceA, MyClass instanceB)
    {
        if(instanceA != null && instanceB != null)
        {
             if(instanceB.Prop1 != null) 
             {
                 instanceA.Prop1 = instanceB.Prop1;
             }

             if(instanceB.PropN != null) 
             {
                 instanceA.PropN = instanceB.PropN;
             }
    }
}

稍后,在代码的某个地方:

someInstanceOfMyClass.Merge(someOtherInstanceOfMyClass);

在一天结束的时候,你已经把这个操作集中在一个扩展方法中,如果你添加或删除你的类的一个属性,你只需要修改扩展方法的实现,你就可以完成所有的事情。

92dk7w1h

92dk7w1h4#

您可以使用此软件包:XASoft
使用foo.merger(bar)方法将2个对象合并为一个动态对象
just like this

var objA = new { a = 1, b = 2, c = 3 };
var newObj = objA.Merger(new { a = "Hey", d = 4, e = 5 });
newObj.e = "There";
newObj.f = 6;
Console.WriteLine(JsonConvert.SerializeObject(newObj));

even if object list works fine too!

private class TestClass
{
    public int X { get; set; }
    public int Y { get; set; }
}
static void Main(string[] args)
{
    var list = new List<TestClass> {
        new TestClass{ X=1,Y=2},
        new TestClass{ X=3,Y=4}
    };
    Console.WriteLine(JsonConvert.SerializeObject(list.ListMerger(i => new
        { X = "null value", Z = i.X == 1 ? 0 : 1 })));
}

哎呀,看起来像javascript语言...

btw,source code click here

osh3o9ms

osh3o9ms5#

我已经创建了一个类似于上面一些答案的方法,但是它返回一个在两个对象之间合并的新对象,并且只在第一个对象的值为空时合并第二个对象的值。

public T MergeObjects<T>(T primary, T secondary)
        {
            T obj = (T)Activator.CreateInstance(typeof(T));
            Type t = typeof(T);

            var properties = t.GetProperties().Where(prop => prop.CanRead && prop.CanWrite);

            foreach (var prop in properties)
            {
                var value = prop.GetValue(primary, null);
                if (value != null)
                    prop.SetValue(obj, value, null);
                else
                {
                    value = prop.GetValue(secondary, null);
                    if (value != null)
                        prop.SetValue(obj, value, null);
                }
            }
            return obj;
        }
muk1a3rh

muk1a3rh6#

为此,我编写了自己的类:ObjectMerger.
基本上它使用反射(可能会因此变慢)。它还包含更多的特性,例如解析循环引用的对象并合并它们。我的ObjectMerger还包含处理更复杂类的机制,如DelegateMemberInfo。这些类将被完全复制,类中的其他对象将递归合并。
语法如下:

var initialInstance = new MyObjectBase(); // Initialize first object
var properInstance = new MyObjectWithAlgorithms(); // Initialize second object
var result = ObjectMerger.MergeObjects(properInstance, initialInstance); // Merge Objects into type of "properInstance"

我很抱歉地说,它不是按原样使用的,因为由于我公司的限制,目前存储库中缺少一些外部库,但它们可以很容易地重写。我希望a将来可以添加它们。

vs91vp4v

vs91vp4v7#

这与@Bas Answer相同,但用于合并2个对象列表

public class Copycontents
{
    public static void Work<T>(IList<T> targetList, IList<T> sourceList, Func<T, int> selector)
    {
        var matchingPrimaryKey = targetList.Select(x => selector(x)).ToList();

        foreach (var thismatchingPrimaryKey in matchingPrimaryKey)
        {
            CopyValues<T>(targetList.Single(x => selector(x) == thismatchingPrimaryKey),
                sourceList.Single(x => selector(x) == thismatchingPrimaryKey));
        }
    }

    private static void CopyValues<T>(T target, T source)
    {
        Type t = typeof(T);

        var properties = t.GetProperties().Where(prop => prop.CanRead && prop.CanWrite);

        foreach (var prop in properties)
        {
            var value = prop.GetValue(source, null);
            if (value != null)
                prop.SetValue(target, value, null);
        }
    }
}

相关问题