2014-12-13 54 views
0

我有一个需要执行Distinct()函数的对象列表。目前我使用下面的代码。Linq表达式:在列表动态属性上执行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的工作。但我不擅长它。所以在这里需要帮助。

谢谢!

+1

传递表达式作为参数传递给函数 – 2014-12-13 09:16:55

+0

我想你可以使用[动态查询库(http://weblogs.asp.net/scottgu/dynamic-linq-part-1-using- the-linq-dynamic-query-library)。 – Leo 2014-12-13 09:26:08

回答

1

可以使用的扩展方法和泛型类型的功率编写一个通用的扩展方法来获得每一个列表(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; 
    } 
} 
+0

谢谢!这也适用。 – 2014-12-13 16:40:07

2

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

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 
+0

这对我的项目具有很大的灵活性。谢谢! – 2014-12-13 16:39:47

1

一个简洁的方式来回答你的问题是使用辉煌Dynamic LinQ extension写:

C#

使用System.Linq的; using System.Linq.Dynamic;

string FieldName =“Zone”;

列表<字符串>选择= 显示列表 。选择(字段名) .Cast <字符串>() .Distinct() .ToList();