Выражение Linq: Выполнить Distinct для динамического свойства списка

1

У меня есть список объектов, на которых мне нужно выполнить функцию Distinct(). В настоящее время я использую следующий код.

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

Вышеприведенный код хорошо работает для меня. Однако мне нужно развернуть этот код во что-то, что позволяет мне указать любое имя свойства и вернуть мне различные значения списка. Мой пользовательский объект имеет свойства 20+, например Zone, Region, Department и т.д.

Мне нужно сделать гибкую функцию, которую я даю любому имени свойства, и он возвращает разные. Что-то вроде этого псевдо:

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

Я считаю, что это работа для Linq Expressions. Но я не гожусь. Так что нужна помощь здесь.

Благодарю!

  • 1
    Передайте выражение в качестве аргумента функции
  • 0
    Я думаю, что вы могли бы использовать динамическую библиотеку запросов для этого.
Теги:
linq
linq-expressions

3 ответа

2
Лучший ответ

Вы можете использовать возможности методов расширения и общих типов для написания общего метода расширения для получения отличного результата из каждого списка (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

С#

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
    Спасибо! Это работает также.
3

Вы можете создать собственный универсальный метод расширения. Также обратите внимание, что перед вызовом 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
    Это имеет хороший потенциал для гибкости в моем проекте. Спасибо!
1

Краткий способ ответить на ваш вопрос - использовать блестящее расширение Dynamic LinQ для записи:

С#

используя System.Linq; используя System.Linq.Dynamic;

string Полеvalue = "Зона";

Список <строка> Выбор = Список отображения.Выберите (Имя поля).Cast <string>().Distinct().ToList();

Ещё вопросы

Сообщество Overcoder
Наверх
Меню