问题
If I have following type hierarchy:
abstract class TicketBase
{
public DateTime PublishedDate { get; set; }
}
class TicketTypeA:TicketBase
{
public string PropertyA { get; set; }
}
class TicketTypeB:TicketBase
{
public string PropertyB { get; set; }
}
and many more TicketTypes : TicketBase
and want to create a function which selects any property e.g. PropertyA
from any ticket type e.g. TicketTypeA
I wrote this function:
private Func<TicketBase, String> CreateSelect(Type t, String FieldName)
{
var parameterExp = Expression.Parameter(t, "sel");
var fieldProp = Expression.PropertyOrField(parameterExp, FieldName);
var lambda = Expression.Lambda<Func<TicketBase, String>>(fieldProp, parameterExp);
return lambda.Compile();
}
and call it on a List<TicketBase> Tickets
like so:
Type typeToSelectFrom = typeof(TicketTypeA);
String propertyToSelect = "PropertyA";
Tickets.Select(CreateSelect(typeToSelectFrom, propertyToSelect));
I get the following ArgumentException:
ParameterExpression of type 'TicketTypes.TicketTypeA' cannot be used for delegate parameter of type 'Types.TicketBase'
Anyone know how to fix this?
回答1:
Well, one option is to include a cast, e.g.
private Func<TicketBase, String> CreateSelect(Type t, String FieldName)
{
var parameterExp = Expression.Parameter(typeof(TicketBase), "sel");
var cast = Expression.Convert(parameterExp, t);
var fieldProp = Expression.PropertyOrField(cast, FieldName);
var lambda = Expression.Lambda<Func<TicketBase, String>>(fieldProp,
parameterExp);
return lambda.Compile();
}
So that calling CreateSelect(typeof(TicketTypeA), "PropertyA")
is equivalent to:
Func<TicketBase, string> func = tb => ((TicketTypeA)tb).PropertyA;
Obviously that's going to fail if you apply it to a TicketBase
value which refers to (say) a TicketTypeB
, but it's hard to avoid that, if you've got a List<TicketBase>
or something similar.
来源:https://stackoverflow.com/questions/5116177/how-do-i-create-a-custom-select-lambda-expression-at-runtime-to-work-with-sub-cl