клонирование объекта в группе linq - замена конструктора копирования - PullRequest
1 голос
/ 11 августа 2010

У меня есть коллекция пользовательских объектов (активов), которые я хочу сгруппировать с помощью LINQ.Пользовательский объект имеет стандартные свойства, такие как id, name и cost property.При группировке я хочу рассчитать стоимость для каждой группы, поэтому я использую небольшую хитрость, подобную этой:

from a in assets
group a by a.AssetId into ga
select new Asset()
                 {
                    AssetId = ga.Key,
                    Cost = ga.Select(gg=>gg.Cost).Sum()
                 }

Хорошо, здесь все хорошо.Но ... чтобы также инициализировать свойства заказа, я использую совместно конструктор копирования и расчеты стоимости ...

from a in assets
group a by a.AssetId into ga
select new Asset(ga.FirstOrDefault())
                 {
                    AssetId = ga.Key,
                    Cost = ga.Select(gg=>gg.Cost).Sum()
                 }

Итак, теперь я получаю коллекцию сгруппированных активов по идентификатору со всеми свойствамископировано из первого актива в группе с вычисленной сгруппированной стоимостью.Но ... для этого мне нужно написать для каждого объекта, использующего этот вид группировки, конструктор копирования с «инициализацией всех свойств», который в моем случае является непроизводительным, поскольку существуют объекты с более чем 20 свойствами.

Я пытался использовать трюк клонирования по ссылке:

Глубокое клонирование объектов

в запросе группы linq, но безуспешно.

Мой вопрос: есть ли лучший / более элегантный способ сделать это?

Спасибо

1 Ответ

2 голосов
/ 11 августа 2010

Если вам не нужно их глубокое копирование, вы можете использовать метод MemberwiseClone. Реализация (происходит из класса Object) и дает вам поверхностную копию. Итак, линия new Asset(ga.FirstOrDefault()) станет ((Asset)(ga.FirstOrDefault().MemberwiseClone())). Однако, будучи мелкой копией, [First Asset] .SomeObject будет указывать на [Grouped Asset] .SomeObject, а изменения одного будут отражаться на другом.

Отредактировано, чтобы включить вспомогательный метод, описанный в комментариях:

static T CloneAndUpdate<T>(T t, Action<T> updater) where T: class
{
T clone = null; // Use reflection/serialization to create shallow/deep clone
updater(clone);
return clone;
}

Теперь вы можете использовать метод следующим образом:

select Utility.CloneAndUpdate(ga.FirstOrDefault(), a =>
             {
                AssetId = ga.Key,
                Cost = ga.Select(gg=>gg.Cost).Sum()
             })
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...