2013-10-30 57 views
0

我目前正在努力获得使用memberexpression集合内的项目完成的方法。 我知道如何写一个memberexpression直接持有集合的成员,但我怎么能告诉它使用它的基础类型。Memberexpression对收集项目

private Collection<TestClass> collection { get; set; } 
DoSomethingWithCollection(collection,() => collection.Count); 

private void DoSomethingWithCollection(Collection<TestClass> collection, MemberExpression member) 
{ 
    foreach(var item in collection) 
    { 
     //use reflexion to get the property for each item 
     //based on the memberexpression and work with it 
    } 
} 

我怎么会需要重写这段代码DoSomethingWithCollection的呼叫可以保持基本类型的集合的Memberexpression,所以从“识别TestClass”?

+0

让我确定我明白了:假设你的'MemberExpression'指向一个属性'Name'。在这种情况下,您只需要读取集合中每个项目的'Name'属性?因为在你的用例中,你传入了一个读取集合本身的属性的lambda('Count')。 –

+0

那是正确的。我只是在集合中的类的属性中进行操作。我提供了Count作为例子,因为这就是我知道如何处理集合“直接”,但我不知道如何处理底层类型。 –

+0

您是否希望能够将lambda作为第二个参数传入,如您的示例中所示? –

回答

1

在您的意见中,您也询问了有关设置属性的问题。也许你真正需要的是像ForEach运营商更广义的解决方案,进行了一个集合中的每个元素一些行动:

public static void ForEach<TSource>(
    this IEnumerable<TSource> source, 
    Action<TSource> action) 
{ 
    if (source == null) 
     throw new ArgumentNullException("source"); 
    if (action== null) 
     throw new ArgumentNullException("action"); 

    foreach (TSource item in source) 
     action(item); 
} 

现在你能读一个属性:

items.ForEach(item => Console.WriteLine(item.Name)); 

.. 。或者设置一个属性:

items.ForEach(item => item.Name = item.Name.ToUpper()); 

...或做别的事:

items.ForEach(item => SaveToDatabase(item)); 

您可以自己编写此扩展方法,但它也是交互式扩展的一部分,它通过反应式扩展的几项功能扩展了LINQ。只需在NuGet上查找“Ix实验”包。

3

你可以使用泛型来实现这一目标更容易,更有效:

private void DoSomethingWithCollection<TClass, TProperty>(
    Collection<TClass> collection, 
    Func<TClass, TProperty> extractProperty) 
{ 
    foreach (var item in collection) 
    { 
     var value = extractProperty(item); 
    } 
} 

这里是你如何使用它(考虑您的藏品有一个“名称”属性):

DoSomethingWithCollection(collection, item => item.Name); 
+0

感谢您的答案看起来非常好,并且比我的reflecion调用属性更容易。只是一个简单的问题,是否可以用这个值来指定一个值,还是仅限于获取一个值? –

+1

是的,但您需要一个不同的委托类型(一个接受目标对象和值),比如'Action '。然后你可以传入'(item,value)=> item.Name = value' –

+0

@MikeStrobel:我试图将代码改为你的建议,但是我没有这么做。我的方法有以下签名:DoSomethingWithCollection (IEnumerable 集合,Action setProperty)(如您所推荐的)。我的电话现在是:DoSomethingWithCollection (this。TabAccountLangs,(lang,value)=> lang.TextAccount =“asdfasdf”); - VS告诉我,我必须直接包含。但我不知道如何正确使用setProperty参数。 setProperty(item,???);什么是第二个参数现在(值?)? –