Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
215 views
in Technique[技术] by (71.8m points)

c# - Declaring Func<in T, out Result> dynamically

Consider this:

var propertyinfo = typeof(Customer).GetProperty(sortExpressionStr);
Type orderType = propertyinfo.PropertyType;

now I want to declare

Func<int,orderType>

I know its not possible directly since ordertype is at runtime but is there is any workaround ?

this is exactly what I want to do :

var propertyinfo = typeof(T).GetProperty(sortExpressionStr);
Type orderType = propertyinfo.PropertyType;

var param = Expression.Parameter(typeof(T), "x");
var sortExpression = (Expression.Lambda<Func<T, orderType>>
   (Expression.Convert(Expression.Property(param, sortExpressionStr), typeof(orderType)), param));

all this because I want to convert:

Expression<Func<T,object>> to Expression<Func<T,orderType>>

or if its not possible then I want to create it from the first place with the right type , the case is as following:

I'm inside a method which have a type(Customer) and a property name of that type I want to order by it , I want to create a sort expression tree to pass it to Orderby (here).

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You can do this by using an open generic type definition, and then making the specific type from that:

typeof(Func<,>).MakeGenericType(typeof(int), orderType);

However, what you're trying to do (calling Lambda<TDelegate>) is not directly possible. You must call Lambda without a type parameter:

var propertyinfo = typeof(T).GetProperty(sortExpressionStr);
Type orderType = propertyinfo.PropertyType;

var param = Expression.Parameter(typeof(T), "x");
var sortExpression = Expression.Lambda(
        Expression.Convert(Expression.Property(param, sortExpressionStr),
                           orderType), 
        param));

This will create the proper Func<,> for you behind the scenes. If you want to compile the expression and use the delegate, you can only do this dynamically with

sortExpression.Compile().DynamicInvoke(param);

If you want to call the OrderBy extension method on Queryable, things get a little more complicated:

var propertyInfo = typeof(T).GetProperty(sortExpressionStr);
Type orderType = propertyInfo.PropertyType;

// first find the OrderBy method with no types specified
MethodInfo method = typeof(Queryable).GetMethods()
  .Where(m => m.Name == "OrderBy" && m.GetParameters().Length == 2)
  .Single();
// then make the right version by supplying the right types
MethodInfo concreteMethod = method.MakeGenericMethod(typeof(T), orderType);

var param = Expression.Parameter(typeof(T), "x");

// the key selector for the OrderBy method
Expression orderBy =
    Expression.Lambda(
        Expression.Property(orderParam, propertyInfo),
        orderParam);

// how to use:
var sequence = new T[0].AsQueryable(); // sample IQueryable

// because no types are known in advance, we need to call Invoke 
// through relection here
IQueryable result = (IQueryable) concreteMethod.Invoke(
                                   null, // = static
                                   new object[] { sequence, orderBy });

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...