Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/331.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 声明函数<;输入T,输出结果>;动态地_C#_Lambda_Expression Trees_Predicate_Anonymous Methods - Fatal编程技术网

C# 声明函数<;输入T,输出结果>;动态地

C# 声明函数<;输入T,输出结果>;动态地,c#,lambda,expression-trees,predicate,anonymous-methods,C#,Lambda,Expression Trees,Predicate,Anonymous Methods,考虑这一点: var propertyinfo = typeof(Customer).GetProperty(sortExpressionStr); Type orderType = propertyinfo.PropertyType; 现在我要申报 Func<int,orderType> 所有这些都是因为我想转换: Expression<Func<T,object>> to Expression<Func<T,orderType>>

考虑这一点:

var propertyinfo = typeof(Customer).GetProperty(sortExpressionStr);
Type orderType = propertyinfo.PropertyType;
现在我要申报

Func<int,orderType>
所有这些都是因为我想转换:

Expression<Func<T,object>> to Expression<Func<T,orderType>>
表达式到表达式
或者,如果不可能,那么我想从第一个位置使用正确的类型创建它,情况如下:

我在一个方法中,该方法有一个
类型(Customer)
和一个我想按其排序的该类型的属性名,我想创建一个排序表达式树,将其传递给
Orderby
(此处)。

您可以使用:

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

这应该起作用:

public static IQueryable<T> OrderByField<T>(
    IQueryable<T> 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<T>(
               Expression.Call(typeof(Queryable),
                               ascending ? "OrderBy" : "OrderByDescending",
                               new Type[] { q.ElementType, x.Body.Type },
                               q.Expression,
                               x));
}
公共静态IQueryable OrderByField(
IQueryable q,字符串sortfield,布尔升序)
{
var p=表达式参数(typeof(T),“p”);
var x=Expression.Lambda(Expression.Property(p,sortfield),p);
返回q.Provider.CreateQuery(
表达式调用(typeof(Queryable),
升序?“OrderBy”:“OrderByDescending”,
新类型[]{q.ElementType,x.Body.Type},
q、 表情,
x) );
}

从。

您可以通过使用打开的泛型类型定义,然后根据该定义生成特定类型来执行此操作:

typeof(Func<,>).MakeGenericType(typeof(int), orderType);
这将在幕后为您创建适当的
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 });

您可以获取与
Func
关联的
类型
,以防您想将其传递到

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

linqClass.OrderBy(GetSortExpression(sortstr));
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;
    }
公共静态表达式GetSortExpression(字符串sortExpressionStr) { var param=表达式参数(类型(T),“x”); var sortExpression=Expression.Lambda(Expression.Property(param,sortExpressionStr),param); 返回排序表达式; }
这解决了我的问题,我用它传递额外的参数Typeof(Object),orderby告诉我它不能按对象类型排序。谢谢大家


谢谢dtb,我将检查您的答案是否有效,如果有效,我将接受。如果无效,我将接受thsi one。

您希望使用Visual Studio示例代码的一部分Dynamic Linq


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

public class Product
{
    public long ID { get; set; }
    public string Name { get; set; }
    public DateTime Date { get; set; }
}


static void Main(string[] args)
{
    List<Product> 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() });
}
公共类产品
{
公共长ID{get;set;}
公共字符串名称{get;set;}
公共日期时间日期{get;set;}
}
静态void Main(字符串[]参数)
{
列出产品=(从可枚举范围(1,10)中的i开始)
选择新产品{ID=i,Name=“Product”+i,Date=DateTime.Now.AddDays(-i)}).ToList();//测试用例
const string SortBy=“Date”;//要进行测试,可以更改为“ID”/“Name”
Type sortType=typeof(Product).GetProperty(SortBy).PropertyType;//日期时间
ParameterExpression sortParamExp=Expression.Parameter(产品类型),“p”);/{p}
表达式sortBodyExp=Expression.PropertyOrField(SORTPAREMXP,SortBy);//{p.DateTime}
LambdaExpression sortExp=Expression.Lambda(sortBodyExp,sortparemxp);//{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,sortExp.Compile()});
}

基于上述情况,将
产品
更改为
T
以使其通用并不困难。

您不能在编译时声明
sortExpression
表达式
类型,因为
orderType
在编译时是未知的,而只有在运行时才知道。编译后,您希望如何使用lambda表达式?好吧,忘了sortexpression吧,有没有可能通过使用propertyname字符串进行排序?我已经扩展了我的答案。这似乎是同一个问题,这种方法保持类型安全。没有伙伴,typeof(orderType)不会编译,我尝试了alreadytypeof(orderType)是不符合逻辑的,因为您在编译时尝试键入,而在运行时尝试键入ordertype,我想我只是好奇:为什么需要表达式。在进行动态排序时,如果不知道要传递哪个属性,请将具有type
ordertype
的属性转换为type
ordertype
?@dtb!什么类型的它,当它作为一个字符串传递给您时,它不会太有效,鲁本,因为这样我就不能使用linqClass.OrderBy(这里)返回DynamicInvoke了;我不确定这是否符合我的情况,也不确定如何测试它,无论如何我都解决了这个问题,感谢无论如何dtb的时间和努力。@Stacker:那么,你是如何解决这个问题的?其他人可能会偶然发现你的问题,并遇到同样的问题。我已经发布了解决方案,并发布了代码中的错误。谢谢你buddyYes如果我使用linq来枚举,而不是linq来sql,我可以使用它,因为这会导致记录的排序,所以如果你只取前10个,跳过它会带来麻烦,因为你需要在重定时记录时使用orderby方法在sql中进行排序!是的,这会起作用,但我不想包含作为源文件而不是程序集分发的动态linq dllIt。您可以将其编译到程序集中,以避免任何额外的引用。看看C:\Program Files(x86)\Microsoft Visual Studio 10.0\Samples\1033\CSharpSamples.zip和压缩文件LinqSamples\DynamicQuery\DynamicQuery\DynamicQuery\Dynamic.cs这对我不起作用。列表=新列表()/*fill list*/当我这样调用时:list.OrderBy(GetSortExpression(“MyColName”))
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 });
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;
    }
public class Product
{
    public long ID { get; set; }
    public string Name { get; set; }
    public DateTime Date { get; set; }
}


static void Main(string[] args)
{
    List<Product> 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() });
}