Объявление Func динамично

anonymous-methods c# expression-trees lambda predicate

Вопрос

Учти это:

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

теперь я хочу объявить

Func<int,orderType>

Я знаю, что это невозможно сразу, так как ordertype находится во время выполнения, но есть ли какое-либо обходное решение?

это именно то, что я хочу сделать:

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

все это, потому что я хочу конвертировать:

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

или если это невозможно, то я хочу создать его с первого места с правильным типом, дело в следующем:

Я внутри метода, который имеет type(Customer) и имя свойства этого типа, которое я хочу заказать им, я хочу создать дерево выражений сортировки, чтобы передать его в Orderby (здесь).

Принятый ответ

linqClass.OrderBy(GetSortExpression(sortstr));


public static Expression<Func<T,object>> GetSortExpression<T>(string sortExpressionStr)
    {
        var param = Expression.Parameter(typeof(T), "x");
        var sortExpression = Expression.Lambda<Func<T, object>>(Expression.Property(param, sortExpressionStr), param);
        return sortExpression;
    }

это сработало, моя проблема заключалась в том, что я использовал для передачи дополнительный параметр Typeof (Object) и orderby, который использовался, чтобы сказать мне, что он не может сортироваться по типу объекта. Спасибо всем

спасибо dtb, я проверю, работает ли ваш ответ, и я приму его, если он сработает, если я не соглашусь с thsi one.


Популярные ответы

Вы можете сделать это, используя определение открытого общего типа, а затем сделав из него определенный тип:

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

Однако то, что вы пытаетесь сделать (вызов Lambda<TDelegate> ), напрямую не возможно. Вы должны вызвать Lambda без параметра типа:

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

Это создаст правильный Func<,> для вас за кулисами. Если вы хотите скомпилировать выражение и использовать делегат, вы можете сделать это только динамически с помощью

sortExpression.Compile().DynamicInvoke(param);

Если вы хотите вызвать OrderBy расширения OrderBy в Queryable , все будет немного сложнее:

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


Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Является ли этот КБ законным? Да, узнайте, почему
Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Является ли этот КБ законным? Да, узнайте, почему