Вызов конструктора с использованием выражения Dynamic Linq Select

Я использую Dynamic Linq.

Я могу сделать следующее:

IQueryable<Person>().Select("new(Id as Id, FirstName + Surname as Name");

Это создает IQueryable (не IQueryable<object>), содержащий анонимный тип.

Но учитывая, что у меня есть следующий класс:

public class ListItem
{
    public ListItem()
    {
    }
    public ListItem(int id, string name)
    {
        this.Id = id;
        this.Name = name;
    }

    public int Id { get; set; }
    public string Name { get; set; }
}

Я хотел бы напрямую выбрать этот тип из моего IQueryable<Person>, вызвав конструктор ListItem, что эквивалентно следующему:

IQueryable<Person>().Select(p => new ListItem(p.Id, p.FirstName + p.Surname));

Я пробовал такие варианты, как:

// Illegal - new expects form "new()" - exception "'(' expected"
IQueryable<Person>().Select("new ListItem(Id, FirstName + Surname)");

// this doesn't work, "No property 'ListItem' exists on type 'Person'"
IQueryable<Person>().Select("ListItem(Id, FirstName + Surname)");

// this doesn't work because "[" is not expected
IQueryable<Person>().Select("[MyProject.Utils.ListItem,MyProject]()");

Я считаю, что это возможно из документации, доступной здесь:

Разрешение перегрузки для методов, конструкторов и индексаторов использует правила, аналогичные C#. Говоря неформальными терминами, разрешение перегрузки выберет лучший метод сопоставления, конструктор или индексатор или сообщит об ошибке неоднозначности, если не может быть идентифицировано ни одного наилучшего совпадения.

Обратите внимание, что вызовы конструктора не имеют префикса new.

Возможно ли это, или я неправильно понял документацию?


person kaitlinsm    schedule 27.10.2015    source источник
comment
Зачем использовать для этого DynamicLinq, а не только LINQ?   -  person Robert McKee    schedule 27.10.2015


Ответы (1)


Я не уверен, поддерживаются ли конструкторы в методе Select в Dynamic Linq. Возможно, в документации говорится, что это поддерживается только для предикатов, таких как выражения, используемые в методе Where. Хотя я не уверен.

В любом случае, это может быть решением для вас:

var result =
    context
        .Customers
        .Select("new(Id as Id, FirstName + Surname as Name")
        .AsEnumerable()
        .Select(x => new ListItem(x.Id, x.Name))
        .ToList();
person Yacoub Massad    schedule 27.10.2015
comment
Я использовал аналогичный подход, но поскольку тип объекта в первом Select генерируется динамически, вы не можете ссылаться на x.Id. Вместо этого вам нужно использовать что-то вроде AutoMapper, например. .Select(x => AutoMapper.Mapper.DynamicMap<ListItem>()). - person kaitlinsm; 02.11.2015
comment
Результатом Select(...).AsEnumerable() является IEnumerable<dynamic>, что означает, что вы можете использовать x.Id. Вы не получите intellisense, но код будет компилироваться и работать корректно. Я действительно пробовал это, прежде чем публиковать ответ. - person Yacoub Massad; 02.11.2015
comment
Упс! Я забыл о dynamic. Спасибо - я думаю, что ответ на мой вопрос заключается в том, что вам нужно выполнить явное преобразование, и что динамический linq по умолчанию не поддерживает создание экземпляров определенных типов. - person kaitlinsm; 02.11.2015