2013-10-24 23 views
1

比方說,我們有一個類泛型列表/子表處理

class ComplexCls 
{ 
    public int Fld1; 
    public string Fld2; 
    //could be more fields 
} 

class Cls 
{ 
    public int SomeField; 
} 

,然後一些代碼

class ComplexClsList: List<ComplexCls>; 
ComplexClsList myComplexList; 
// fill myComplexList 

// same for Cls  
class ClsList : List<Cls>; 
ClsList myClsList; 

我們要填充從myComplexList myClsList,像(僞)的東西:

foreach Complexitem in myComplexList 
{ 
    Cls ClsItem = new Cls(); 
    ClsItem.SomeField = ComplexItem.Fld1; 
} 

執行此操作的代碼很簡單,將放入myClsList的某些方法中。 但是我想爲通用ComplexCls儘可能通用地設計它。 請注意,在使用此代碼時,確切的ComplexCls是已知的,只有shd算法是通用的。
我知道它可以使用(直接)反射來完成,但是還有其他解決方案嗎? 讓我知道,如果問題不夠清楚。 (可能不是)。編輯]基本上,我需要的是:有myClsList,我需要指定一個DataSource(ComplexClsList)和一個字段從該數據源(Fld1)將用於填充我的SomeField

+4

聽起來像你正在尋找AutoMapper – SLaks

+0

當你從'List '繼承時,你已經拿走了通用解決方案的能力。我想我們需要更多的細節.. –

+0

我剛剛編輯了我的問題,請再讀一遍。你們很快! – user628661

回答

4

這只是一個映射,所以用一些簡單的LINQ:

ClsList myClsList = new ClsList(); 
myClsList.AddRange(
    myComplexList.Select(Complexitem => new Cls { SomeField = Complexitem.Fld1 }) 
); 
+0

'.ToList()'不返回'ClsList' – StriplingWarrior

+0

@StriplingWarrior這是一個很好的觀點..固定! –

+1

除非'ClsList'具有一些功能,否則OP可能更適合用'IEnumerable '...... –

0

你可能需要重新考慮在第一時間延長List類。在這種情況下繼承給你什麼?我懷疑你在這裏偏好composition over inheritance。一種可能的方法是:

// If you would say that a ComplexCls "is a" Cls, then maybe your inheritance 
// relationship belongs here instead. 
public class ComplexCls : Cls { 
} 

public class ClsList 
{ 
    public IReadOnlyCollection<Cls> Items {get;set;} 
} 

public class ComplexClsList 
{ 
    public IReadOnlyCollection<ComplexCls> Items {get;set;} 
} 

然後你可以很容易地創建一個ClsClist。

ClsList basicList = new ClsList{Items = complexList.Items}; 

但是你可能想要把它一步越走越質疑爲什麼ClsListComplexClsList類存在於所有。爲什麼不直接通過List s。我的意思是,ClsList和「Cls列表」(List<Cls>)之間有什麼區別?

+0

'ComplexCls'和'Cls'是不兼容的類型,所以你必須做一些事情,而不是複製引用到'Items' –

+0

@JacobKrall:好點。 – StriplingWarrior

+0

我想我可以把這個映射功能放在ClsList的基類中,所以我可以在每次從ClsListBase派生一個新的ClsList類時重用它,而不必再次編寫代碼 – user628661

2

好,越容易版本假設我們對一類已知目標字段(我寫這是一個擴展方法,沒有必要做

public IEnumerable<Cls> MapField<TSource>(IEnumerable<TSource> sourceList, 
              Func<TSource, int> sourceSelector) 
{ 
    return sourceList.Select(x => new Cls {SomeField = sourceSelector(x)}); 
} 

稱這種方式

IEnumerable<Cls> result = MapField(myComplexList, x => x.Fld1); 

除了:由於從List你的類型的myComplexListComplexClsList繼承(實現IEnumerable這將工作結果是ClsList類型的不是你想要的,但你可以很容易地調用.ToList()的結果,並提供ClsList構造函數,需要List<Cls>


而且更復雜的版本時,我們不知道目標字段(或類型)...

public IEnumerable<TResult> MapField<TSource, TResult, TMap>(
    IEnumerable<TSource> sourceList, 
    Func<TSource, TMap> sourceSelector, 
    Func<TMap, TResult> resultCreator) 
{ 
    return sourceList.Select(x => resultCreator(sourceSelector(x))); 
} 

不漂亮叫....

IEnumerable<Cls> result = MapField(
    myComplexList, 
    source => source.Fld1, 
    valueToMap => new Cls() {SomeField = valueToMap}); 

可能是一種更好的方式,但目前它不會發生在我身上。

編輯:其實,你可以在最後一個結合兩種Func到一個單一的一個,需要一個TSource並創建和必要的字段映射到TResult,但我真的不知道你與獲得什麼額外的抽象層...

+2

......具有諷刺意味的是,畢竟這種努力,調用MapField方法與它要取代的LINQ代碼一樣複雜和重複。 – StriplingWarrior

+1

嘿嘿...嗯,回到AutoMapper? ;) –

+0

這看起來不錯!謝謝! – user628661