Search code examples
c#linqdynamicconstructorinvocation

Constructor Invocation using Dynamic Linq Select Expression


I'm using Dynamic Linq.

I can do the following:

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

This creates an IQueryable (not an IQueryable<object>) containing an anonymous type.

But given I have the following class:

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; }
}

I would like to select directly into this type from my IQueryable<Person> by invoking the constructor of ListItem, equivalent to the following:

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

I've tried variants such as:

// 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]()");

I believe this to be possible from the documentation available here:

Overload resolution for methods, constructors, and indexers uses rules similar to C#. In informal terms, overload resolution will pick the best matching method, constructor, or indexer, or report an ambiguity error if no single best match can be identified.

Note that constructor invocations are not prefixed by new.

Is this possible or have I misunderstood the documentation?


Solution

  • I am not sure if constructors are supported in the Select method in Dynamic Linq. Maybe the documentation is saying that this is only supported for predicates, like the expressions that are used in the Where method. I am not sure though.

    Anyway, this might be a solution for you:

    var result =
        context
            .Customers
            .Select("new(Id as Id, FirstName + Surname as Name")
            .AsEnumerable()
            .Select(x => new ListItem(x.Id, x.Name))
            .ToList();