声明Func 动态

考虑一下:

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

现在我想宣布

 Func 

我知道它不可能直接因为ordertype是在运行时但有任何解决方法吗?

这正是我想要做的:

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

这一切都是因为我想转换:

 Expression<Func> to Expression<Func> 

或者如果它不可能那么我想从正确的类型的第一个地方创建它,案例如下:

我在一个方法里面有一个type(Customer)和一个我希望按其订购的类型的属性名称,我想创建一个排序表达式树来将它传递给Orderby (这里)。

您可以使用Type.MakeGenericType方法 :

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

这应该工作:

 public static IQueryable OrderByField( IQueryable q, string sortfield, bool ascending) { var p = Expression.Parameter(typeof(T), "p"); var x = Expression.Lambda(Expression.Property(p, sortfield), p); return q.Provider.CreateQuery( Expression.Call(typeof(Queryable), ascending ? "OrderBy" : "OrderByDescending", new Type[] { q.ElementType, x.Body.Type }, q.Expression, x)); } 

从这里开始 。

您可以通过使用开放的generics类型定义,然后从中创建特定类型来执行此操作:

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

但是,您正在尝试做的事情(调用Lambda )是不可能的。 您必须在没有类型参数的情况下调用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); 

如果你想在Queryable上调用OrderBy扩展方法,事情会变得复杂一些:

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

您想使用Dynamic Linq,它是Visual Studio示例代码的一部分。

使用Dynamic Linq的示例代码

http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx

您可以获取与Func关联的Type ,以防您想要将其传递给CreateDelegate 。

但是你最终想要用它做什么? 可能有一种更直接的方法。

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

这工作我的问题是我曾经传递额外的参数Typeof(对象)和orderby用于告诉我它不能按对象类型排序。 谢谢大家

谢谢dtb我会检查你的答案是否也能正常工作,如果不能,我会接受它,否则我会接受你的答案。

看看我的解决方案是否足够动态

 public class Product { public long ID { get; set; } public string Name { get; set; } public DateTime Date { get; set; } } static void Main(string[] args) { List products = (from i in Enumerable.Range(1, 10) select new Product { ID = i, Name = "product " + i, Date = DateTime.Now.AddDays(-i) }).ToList(); //the test case const string SortBy = "Date"; // to test you can change to "ID"/"Name" Type sortType = typeof(Product).GetProperty(SortBy).PropertyType; // DateTime ParameterExpression sortParamExp = Expression.Parameter(typeof(Product), "p"); // {p} Expression sortBodyExp = Expression.PropertyOrField(sortParamExp, SortBy); // {p.DateTime} LambdaExpression sortExp = Expression.Lambda(sortBodyExp, sortParamExp); // {p=>p.DateTime} var OrderByMethod = typeof(Enumerable).GetMethods().Where(m => m.Name.Equals("OrderBy") && m.GetParameters().Count() == 2).FirstOrDefault().MakeGenericMethod(typeof(Product), sortType); var result = OrderByMethod.Invoke(products, new object[] { products, sortExp.Compile() }); } 

基于上述内容,将Product更改为T以使其通用并不困难。