объединение двух объектов в C # - PullRequest
29 голосов
/ 02 января 2012

У меня есть объектная модель MyObject с различными свойствами.В какой-то момент у меня есть два экземпляра этого MyObject: экземпляр A и экземпляр B. Я хотел бы скопировать и заменить свойства экземпляра A на свойства экземпляра B, если экземпляр B имеет ненулевые значения.

Если бы у меня был только 1 класс с 3-мя свойствами, нет проблем, я бы легко запрограммировал его (что я и начал делать).Но на самом деле у меня есть 12 различных объектных моделей с примерно 10 свойствами в каждой.

Какой хороший способ сделать это?

Ответы [ 6 ]

42 голосов
/ 02 января 2012

Обновление Используйте AutoMapper вместо этого, если вам нужно часто вызывать этот метод. Automapper создает динамические методы, используя 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 () , указывая флаги привязки.

7 голосов
/ 21 апреля 2012

Я попытался объединить два объекта в анонимный тип от Кайла Финли, и он работает отлично.

С TypeMerger объединение так же просто, как

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

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

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

Вот и все, у вас есть объединенный объект, кроме того, есть возможность игнорировать определенные свойства. То же самое можно использовать и для MVC3.

2 голосов
/ 02 января 2012

Вы можете сделать это с помощью рефлексии, но, как кто-то сказал, это приведет к снижению производительности.

Поскольку вы работаете с ожидаемым дизайном класса, вы можете достичь той же цели с помощью метода расширения, например, так:

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

В конце дня вы централизовали эту операцию в методе расширения, и если вы добавляете или удаляете свойство вашего класса, вам нужно всего лишь изменить реализацию метода расширения, и вы все сделаете.

0 голосов
/ 16 марта 2019

Вы можете использовать этот пакет: XASoft

использовать метод foo.Merger (bar) объединить 2 объекта в динамический объект

просто так

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

, даже если список объектов работает нормально!

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 ...

кстати, исходный код нажмите здесь

0 голосов
/ 22 сентября 2016

Я написал для этого свой собственный класс: ObjectMerger .

В основном он использует отражения (и может быть медленным из-за этого).Он также содержит больше функций, например, анализирует объекты для циклических ссылок и объединяет их.Мой ObjectMerger также содержит механизм для обработки более сложных классов, таких как Delegate или MemberInfo.Они будут полностью скопированы, другие объекты в классе будут рекурсивно объединены.

Синтаксис выглядит следующим образом:

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"

Извините, но не для использования,потому что некоторые внешние библиотеки отсутствуют в хранилище на данный момент из-за ограничений в моей компании, но их легко переписать.Я надеюсь, что смогу добавить их в будущем.

0 голосов
/ 04 апреля 2016

Это то же самое, что и @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);
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...