Как динамически создать выражение> - PullRequest
0 голосов
/ 14 ноября 2018

У меня есть такой класс:

public class Student
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string LOANIDBPM { get; set; }
    public string REPORTTYPE { get; set; }
}

У меня есть список студентов, Я хочу отфильтровать студента в списке по LOANIDBPM и REPORTTYPE.

Обычно это код (с использованием linq)

public void GetListStudent(List<Student> listStudent)
{
    listStudent = listStudent.Where(x => x.LOANIDBPM == "MIKEN" && x.REPORTTYPE == "DX").ToList();
}

Однако по какой-то причине я не могу явный «Список», Мое решение ниже:

public void GetListStudent(object[] listStudent)
{
    ParameterExpression param = Expression.Parameter(listStudent.First().GetType(), nameof(listStudent));
    Expression propLoanBPM = Expression.Property(param, "LOANIDBPM");
    Expression<Func<string>> loanIdLampda = () => "MIKEN";
    Expression searchLoanBPM = Expression.Equal(propLoanBPM, loanIdLampda.Body);

    Expression propReportType = Expression.Property(param, "REPORTTYPE");
    Expression<Func<string>> reportTypeLampda = () => "DX";

    Expression searchReportType = Expression.Equal(propReportType, reportTypeLampda.Body);

    Expression searchFinal = Expression.And(searchLoanBPM, searchReportType);


    Expression<Func<???, bool>> lampda = Expression.Lambda<Func<???, bool>>(searchFinal, param);

    listStudent = listStudent.Where(lampda).ToArray();
}

Приведенный выше код имеет две проблемы:

1: я не знаю тип ученика в функции выражения, Я не могу использовать как:

Expression<Func< listStudent.First().GetType(), bool>> lampda = Expression.Lambda<Func< listStudent.First().GetType(), bool>>(searchFinal, param);

2: В методе Where требуется IQueryable, но в моем коде есть Expression Func.

Извините за мой английский. Большое вам спасибо

1 Ответ

0 голосов
/ 14 ноября 2018

Ваш первый пример не компилируется, потому что listStudent - это список, а LINQ, как правило, возвращает IEnumerable некоторого вида.Вам нужно добавить ToList():

public void GetListStudent(List<Student> listStudent)
{
    listStudent = listStudent
        .Where
        (
            x => x.LOANIDBPM == "MIKEN" && x.REPORTTYPE == "DX"
        )
        .ToList();  //<-- add this
}

Ваш второй пример не работает, потому что c # не знает, что ваш массив объектов на самом деле представляет собой список студентов.Вы можете сказать это, используя метод Cast<>().Когда вы закончите, вам нужно преобразовать обратно в массив, поэтому добавьте ToArray() в конце.

public void GetListStudent(object[] listStudent)
{
    listStudent = listStudent
        .Cast<Student>()  //<-- add this
        .Where
        (
            x => x.LOANIDBPM == "MIKEN" && x.REPORTTYPE == "DX"
        )
        .ToArray();       //<-- and this
}

Если известно, что только некоторые объекты являются студентами, вы можете использовать OfType<>() чтобы отфильтровать их.

public void GetListStudent(object[] listStudent)
{
    listStudent = listStudent
        .OfType<Student>()  //<-- add this
        .Where
        (
            x => x.LOANIDBPM == "MIKEN" && x.REPORTTYPE == "DX"
        )
        .ToArray();       //<-- and this
}

И если вы абсолютно не представляете, что это за объекты, но совершенно уверены, что они обладают свойствами LOANIDBPM и REPORTTYPE, я полагаю, вы могли бы использовать dynamic:

public void GetListStudent(List<dynamic> listStudent)
{
    listStudent = listStudent
        .Where
        (
            x => x.LOANIDBPM == "MIKEN" && x.REPORTTYPE == "DX"
        )
        .ToList();
}
...