Подтвердить что ты не робот

Объединение двух объектов в С#

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

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

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

4b9b3361

Ответ 1

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

Ответ 2

Я пробовал Слияние двух объектов в анонимный тип от Kyle Finley и работает отлично.

С TypeMerger слияние так же просто, как

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

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

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

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

Ответ 3

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

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

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

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

Ответ 4

Это то же самое, что и @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);
        }
    }
}

Ответ 5

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

В основном он использует отражения (и может быть медленным из-за этого). Он также содержит больше возможностей, например. разбор объектов для циклических ссылок и их объединение. My 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"

Мне жаль говорить, что это НЕ ДЛЯ ИСПОЛЬЗОВАНИЯ КАК ЕСТЬ, потому что в настоящее время в репозитории отсутствуют некоторые внешние библиотеки из-за ограничений в моей компании, но их можно легко переписать. Я надеюсь, что они могут добавить их в будущем.