Home > Enterprise >  Cannot cast selector in LINQ Select to correct type
Cannot cast selector in LINQ Select to correct type

Time:09-30

I am trying to have a dynamic Retrieve function where I could pass in a .Select() selector of a custom type.

public IEnumerable<BookableResourceBooking> RetrieveBookingsForWorkOrder(Guid workOrderId, Expression<Func<BookableResourceBooking, dynamic>> selector)
    {
        return (IEnumerable<BookableResourceBooking>)
            CrmServiceContext.BookableResourceBookingSet
            .Where(x => x.msdyn_WorkOrder.Id == workOrderId)
            .Select(selector);
    }

And I call it like this:

.RetrieveBookingsForWorkOrder(
  workOrderId,
  x => new BookableResourceBooking() { Id = x.Id, StartTime = x.StartTime, EndTime = x.EndTime })

This throws an error:

Microsoft.Xrm.Sdk.InvalidPluginExecutionException: 'Unable to cast object of type 'Microsoft.Xrm.Sdk.Linq.Query`1[System.Object]' to type 'System.Collections.Generic.IEnumerable`1[GiGA.Common.Crm.BookableResourceBooking]'.

If I put the selector there manually, it works:

.Select(x => new BookableResourceBooking() { Id = x.Id, StartTime = x.StartTime, EndTime = x.EndTime }); // this is fine

How should I call the function with the selector in the parameter?

CodePudding user response:

The type dynamic is just object as far as the compiled IL is concerned. It just tells the compiler not to throw errors on methods that aren't found.

So this code:

public IEnumerable<BookableResourceBooking> RetrieveBookingsForWorkOrder(
    Guid workOrderId, Expression<Func<BookableResourceBooking, dynamic>> selector)
{
    return (IEnumerable<BookableResourceBooking>)
        CrmServiceContext.BookableResourceBookingSet
        .Where(x => x.msdyn_WorkOrder.Id == workOrderId)
        .Select(selector);
}

Is the same as this:

public IEnumerable<BookableResourceBooking> RetrieveBookingsForWorkOrder(
    Guid workOrderId, Expression<Func<BookableResourceBooking, object>> selector)
{
    return (IEnumerable<BookableResourceBooking>)
        CrmServiceContext.BookableResourceBookingSet
        .Where(x => x.msdyn_WorkOrder.Id == workOrderId)
        .Select(selector);
}

So the .Select(selector) is returning an IEnumerable<object> and you're trying to cast it to (IEnumerable<BookableResourceBooking>).

The question is why is selector defined this way?

  • Related