Déclarer Func dynamiquement

anonymous-methods c# expression-trees lambda predicate

Question

Considère ceci:

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

maintenant je veux déclarer

Func<int,orderType>

Je sais que ce n'est pas possible directement, car ordertype est à l'exécution, mais existe-t-il une solution de contournement?

c'est exactement ce que je veux faire:

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

tout cela parce que je veux convertir:

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

ou si ce n'est pas possible alors je veux le créer à partir du premier endroit avec le bon type, le cas est le suivant:

Je suis dans une méthode qui a un type(Customer) et un nom de propriété de ce type que je souhaite commander, je veux créer un arbre d'expression de tri pour le transmettre à Orderby (ici).

Réponse acceptée

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

cela a fonctionné, mon problème était que je passais le paramètre supplémentaire Typeof (Object) et orderby m'avait dit qu'il ne pouvait pas trier par type d'objet. Merci a tous

merci dtb je vérifierai si votre réponse fonctionne aussi et je l'accepterai si cela fonctionne sinon je l'accepterai.


Réponse populaire

Vous pouvez le faire en utilisant une définition de type générique ouverte, puis en créant le type spécifique à partir de celui-ci:

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

Cependant, ce que vous essayez de faire (appeler Lambda<TDelegate> ) n’est pas directement possible. Vous devez appeler Lambda sans paramètre de type:

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

Cela créera le bon Func<,> pour vous dans les coulisses. Si vous voulez compiler l'expression et utiliser le délégué, vous ne pouvez le faire que de manière dynamique avec

sortExpression.Compile().DynamicInvoke(param);

Si vous souhaitez appeler la méthode d'extension OrderBy sur Queryable , les choses se compliquent un peu:

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



Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi