2013-10-24 25 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