Linq表达式:对列表动态属性执行不同

时间:2014-12-13 08:31:07

标签: c# vb.net linq linq-expressions

我有一个对象列表,我需要在其上执行Distinct()函数。目前我使用以下代码。

Return choices = displaylist
    .Select(Function(x) x.Zone)
    .ToList
    .Distinct()

以上代码适合我。但是,我需要将此代码扩展为允许我提供任何属性名称并返回列表的不同值的内容。我的自定义对象有20多个属性,例如区域,地区,部门等。

我需要创建一个灵活的函数,我给出任何属性名称,它返回不同的。像这样的伪:

Function GetDistincts(PROPERTYNAME as string)
    Return choices = displaylist
        .Select(Function(x) x.[PROPERTYNAME])
        .ToList
        .Distinct()
End Function

我相信这是Linq Expressions的工作。但我不擅长。所以在这里需要帮助。

谢谢!

3 个答案:

答案 0 :(得分:3)

您可以创建自定义通用扩展方法。另请注意,您应该在调用 ToList 之前调用distinct ,因为这将编译表达式;使查询效率降低。

Dim result = displaylist.Property("Zone").Distinct().ToList()
Imports System.ComponentModel
Imports System.Runtime.CompilerServices

Public Module Extensions

    <Extension()>
    Public Function [Property](Of TSource)(source As IEnumerable(Of TSource), name As String) As IEnumerable(Of Object)
        Dim descriptor As PropertyDescriptor = TypeDescriptor.GetProperties(GetType(TSource)).Find(name, True)
        Return source.Select(Function(item As TSource) descriptor.GetValue(item))
    End Function

    <Extension()>
    Public Function [Property](Of TSource, TResult)(source As IEnumerable(Of TSource), name As String) As IEnumerable(Of TResult)
        Dim descriptor As PropertyDescriptor = TypeDescriptor.GetProperties(GetType(TSource)).Find(name, True)
        Return source.Select(Function(item As TSource) CType(descriptor.GetValue(item), TResult))
    End Function

End Module

答案 1 :(得分:2)

您可以使用扩展方法和泛型类型的强大功能来编写通用扩展方法,以获得每个List(Of T)的不同结果:

<强> VB

Dim objects = New List(Of TestObject)()
objects.Add(New TestObject(1, "Test1"))
objects.Add(New TestObject(1, "Test2"))
objects.Add(New TestObject(1, "Test3"))
objects.Add(New TestObject(2, "Test4"))
objects.Add(New TestObject(2, "Test5"))
objects.Add(New TestObject(2, "Test6"))

Dim t As List(Of Integer) = objects.GetDistict(Of Integer, TestObject)("Zone")

Public Class TestObject
    Public Property Zone As Integer
    Public Property Address As String

    Public Sub New(z As Integer, a As String)
        Zone = z
        Address = a
    End Sub
End Class

    Public NotInheritable Class DistinctExtension
    Private Sub New()
    End Sub
    <System.Runtime.CompilerServices.Extension> _
    Public Shared Function GetDistict(Of T, S)(source As List(Of S), name As String) As List(Of T)
        Return source.[Select](Function(x) DirectCast(x.[GetType]().GetProperty(name).GetValue(x), T)).Distinct().ToList()
    End Function

End Class

<强> C#

var objects = new List<TestObject>();
            objects.Add(new TestObject(1,"Test1"));
            objects.Add(new TestObject(1,"Test2"));
            objects.Add(new TestObject(1,"Test3"));
            objects.Add(new TestObject(2,"Test4"));
            objects.Add(new TestObject(2,"Test5"));
            objects.Add(new TestObject(2,"Test6"));

        List<int> t = objects.GetDistict<int, TestObject>("Zone");

public static class DistinctExtension
{
    public static List<T> GetDistict<T,S>(this List<S> source, string name)
    {
        return source.Select(x => (T)x.GetType().GetProperty(name).GetValue(x)).Distinct().ToList();
    }

}

public class TestObject
{
    public int Zone { get; set; }
    public string Address { get; set; }

    public TestObject(int zone, string address)
    {
        Zone = zone;
        Address = address;
    }
}

答案 2 :(得分:1)

回答问题的简明方法是使用辉煌的Dynamic LinQ extension来写:

<强> C#

  

使用System.Linq;      使用System.Linq.Dynamic;

     

string FieldName =&#34; Zone&#34 ;;

     

列表与LT;串GT;选择= 显示列表          。选择(字段名)          .Cast&LT;串GT;()          。不同()          .ToList();