我有一個基類(抽象)有多種實現,其中一些含有其他實現的集合屬性 - 像這樣:反思,逆變和多態性
class BigThing : BaseThing
{
/* other properties omitted for brevity */
List<SquareThing> Squares { get; set; }
List<LittleThing> SmallThings { get; set;}
/* etc. */
}
現在有時我得到一個BigThing,我需要將它映射到另一個BigThing以及它的所有BaseThings集合。但是,如果發生這種情況,我需要能夠判斷源BigThing中的BaseThing是否爲BaseThing,因此應該將其添加到目標BigThing的集合中,或者它是否爲現有 BaseThing應映射到目標集合中已存在的BaseThings之一。 BaseThing的每個實現都有一套不同的匹配標準,對其進行評估以評估新功能。我有以下通用擴展方法來評估此:
static void UpdateOrCreateThing<T>(this T candidate, ICollection<T> destinationEntities) where T : BaseThing
{
var thingToUpdate = destinationEntites.FirstOrDefault(candidate.ThingMatchingCriteria);
if (thingToUpdate == null) /* Create new thing and add to destinationEntities */
else /* Map thing */
}
這工作正常。不過,我認爲我迷戀BigThe的交易方式。我想讓這個方法是通用的,因爲有幾種不同的BigThings,我不想爲每個方法編寫方法,如果我添加集合屬性,我不想改變我的方法。我寫了下面的通用方法是利用反射的,但它不是
void MapThing(T sourceThing, T destinationThing) where T : BaseThing
{
//Take care of first-level properties
Mapper.Map(sourceThing, destinationThing);
//Now find all properties which are collections
var collectionPropertyInfo = typeof(T).GetProperties().Where(p => typeof(ICollection).IsAssignableFrom(p.PropertyType));
//Get property values for source and destination
var sourceProperties = collectionPropertyInfo.Select(p => p.GetValue(sourceThing));
var destinationProperties = collectionPropertyInfo.Select(p => p.GetValue(destinationThing));
//Now loop through collection properties and call extension method on each item
for (int i = 0; i < collectionPropertyInfo.Count; i++)
{
//These casts make me suspicious, although they do work and the values are retained
var thisSourcePropertyCollection = sourceProperties[i] as ICollection;
var sourcePropertyCollectionAsThings = thisSourcePropertyCollection.Cast<BaseThing>();
//Repeat for destination properties
var thisDestinationPropertyCollection = destinationProperties[i] as ICollection;
var destinationPropertyCollectionAsThings = thisDestinationPropertyCollection.Cast<BaseThing>();
foreach (BaseThing thing in sourcePropertyCollectionAsThings)
{
thing.UpdateOrCreateThing(destinationPropertyCollectionAsThings);
}
}
}
這編譯和運行,以及擴展方法成功運行(如預期的匹配和映射),但在destinationThing
集合屬性值保持不變。我懷疑我已經失去了所有鑄造的原始destinationThing
屬性的參考,並分配給其他變量等。我的方法在這裏存在根本上的缺陷嗎?我錯過了一個更明顯的解決方案嗎?或者是我的代碼中有一些簡單的錯誤導致了不正確的行爲?
您的標題需要「...哦,我的!」在末尾;) – Plutonix 2014-10-17 00:41:01
我認爲它:)但我擔心奧茲/東方模特巫師;) – NWard 2014-10-17 01:10:04
不幸的是,你不顯示所有的代碼。所以沒有人能看到你如何初始化「destinationPropertyCollectionAsThings」對象。當然,這就是這個問題的核心。你真的應該發佈一個簡明但完整的代碼示例,可靠地演示該問題。 – 2014-10-17 01:27:00