Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/24.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>;变成表达<;Func<;T>&燃气轮机;_C#_.net_Linq To Sql_Expression Trees - Fatal编程技术网

C# 重构函数<;T>;变成表达<;Func<;T>&燃气轮机;

C# 重构函数<;T>;变成表达<;Func<;T>&燃气轮机;,c#,.net,linq-to-sql,expression-trees,C#,.net,Linq To Sql,Expression Trees,我有一个方法,当前将Func作为参数,但我需要它是表达式。使用AdventureWorks,下面是一个我想使用Func做的示例 private static void DoSomethingWithFunc(Func<Product, string> myFunc) { using (AdventureWorksDataContext db = new AdventureWorksDataContext()) { var result = db.Pro

我有一个方法,当前将
Func
作为参数,但我需要它是
表达式
。使用AdventureWorks,下面是一个我想使用Func做的示例

private static void DoSomethingWithFunc(Func<Product, string> myFunc)
{
    using (AdventureWorksDataContext db = new AdventureWorksDataContext())
    {
        var result = db.Products.GroupBy(product => new
        {
            SubCategoryName = myFunc(product),
            ProductNumber = product.ProductNumber
        });
    }
}
但是我确实需要
product
变量,因为我确实需要键的第二部分(ProductNumber)。所以我不确定现在该怎么办。我不能把它作为一个函数,因为这会引起问题。我不知道如何使用表达式,因为我不知道如何将
product
变量传递给它。有什么想法吗

EDIT:下面是一个如何调用该方法的示例:

DoSomethingWithFunc(product => product.ProductSubcategory.Name);

再想一想,编译表达式是行不通的

您需要手工构建GroupBy表达式,这意味着您不能使用匿名类型。我建议构建表达式的其余部分,然后反编译以查看生成的表达式树。最终结果如下所示,根据需要使用
myExpression
的部分内容:

private static void DoSomethingWithExpression(Expression<Func<Product, string>> myExpression)
{
    var productParam = myExpression.Parameters[0];

    ConstructorInfo constructor = ...; // Get c'tor for return type

    var keySelector = Expression.Lambda(
                          Expression.New(constructor,
                              new Expression[] {
                                  productParam.Body,
                                  ... // Expressions to init other members
                              },
                              new MethodInfo[] { ... }), // Setters for your members
                          new [] { productParam });

    using (AdventureWorksDataContext db = new AdventureWorksDataContext())
    {
        var result = db.Products.GroupBy(keySelector);

        // ...
    }
}
private static void DoSomethingWithExpression(表达式myExpression)
{
var productParam=myExpression.Parameters[0];
ConstructorInfo构造函数=…;//获取返回类型的c'tor
var keySelector=Expression.Lambda(
表达式.New(构造函数,
新表达式[]{
productParam.Body,
…//初始化其他成员的表达式
},
new MethodInfo[]{…}),//成员的设置程序
新[]{productParam});
使用(AdventureWorksDataContext db=new AdventureWorksDataContext())
{
var结果=db.Products.GroupBy(keySelector);
// ...
}
}

无法将表示为
表达式的表达式树
对象拼接到由lambda表达式表示的“树文字”的中间。您必须构建表达式树以手动传递到
GroupBy

// Need an explicitly named type to reference in typeof()
private class ResultType
{
     public string SubcategoryName { get; set; }
     public int ProductNumber { get; set; }|
}

private static void DoSomethingWithExpression(
    Expression<Func<Product,
    string>> myExpression)
{
    var productParam = Expression.Parameter(typeof(Product), "product");
    var groupExpr = (Expression<Func<Product, ResultType>>)Expression.Lambda(
        Expression.MemberInit(
           Expression.New(typeof(ResultType)),
           Expression.Bind(
               typeof(ResultType).GetProperty("SubcategoryName"),
               Expression.Invoke(myExpression, productParam)),
           Expression.Bind(
               typeof(ResultType).GetProperty("ProductNumber"),
               Expression.Property(productParam, "ProductNumber"))),
        productParam);
    using (AdventureWorksDataContext db = new AdventureWorksDataContext())
    {
        var result = db.Products.GroupBy(groupExpr);
    }
}
//需要在typeof()中引用显式命名的类型
私有类ResultType
{
公共字符串子类别名称{get;set;}
public int ProductNumber{get;set;}|
}
私有静态void DoSomethingWithExpression(
表达式(myExpression)
{
var productParam=表达式参数(产品类型),“产品”);
var groupExpr=(表达式)Expression.Lambda(
Expression.MemberInit(
Expression.New(typeof(ResultType)),
表达式绑定(
typeof(ResultType).GetProperty(“子类别名称”),
Expression.Invoke(myExpression,productParam)),
表达式绑定(
typeof(ResultType).GetProperty(“ProductNumber”),
Expression.Property(productParam,“ProductNumber”)),
productParam);
使用(AdventureWorksDataContext db=new AdventureWorksDataContext())
{
var result=db.Products.GroupBy(groupExpr);
}
}

你错过了他从
Func
转到
Expression
的最初原因-他希望这在LINQ到SQL的上下文中工作,这不允许在查询中随机调用函数(或委托)。你击败了Pavel,但他的答案对我来说更清楚+谢谢你的帮助。谢谢我同意帕维尔的答案更好。我的代码基于为构造匿名类型而生成的表达式;MemberInit是命名类型所需的。很好!不过,最后一行不是为我编译的,因为结果被分配给了。“无法从用法推断方法…的类型参数。”我是否遗漏了什么?应将
Expression.Lambda
中的返回值转换为
Expression
。非常好!这比我想象的要复杂得多。我以前从未做过这样的表达,所以我将学习这段代码以确保我完全理解发生了什么。谢谢是的——学习如何手动构建表达式树永远不会太早;有很多常见的场景都需要它…看起来你也可以说Expression.Lambda(…而不是casting。
private static void DoSomethingWithExpression(Expression<Func<Product, string>> myExpression)
{
    var productParam = myExpression.Parameters[0];

    ConstructorInfo constructor = ...; // Get c'tor for return type

    var keySelector = Expression.Lambda(
                          Expression.New(constructor,
                              new Expression[] {
                                  productParam.Body,
                                  ... // Expressions to init other members
                              },
                              new MethodInfo[] { ... }), // Setters for your members
                          new [] { productParam });

    using (AdventureWorksDataContext db = new AdventureWorksDataContext())
    {
        var result = db.Products.GroupBy(keySelector);

        // ...
    }
}
// Need an explicitly named type to reference in typeof()
private class ResultType
{
     public string SubcategoryName { get; set; }
     public int ProductNumber { get; set; }|
}

private static void DoSomethingWithExpression(
    Expression<Func<Product,
    string>> myExpression)
{
    var productParam = Expression.Parameter(typeof(Product), "product");
    var groupExpr = (Expression<Func<Product, ResultType>>)Expression.Lambda(
        Expression.MemberInit(
           Expression.New(typeof(ResultType)),
           Expression.Bind(
               typeof(ResultType).GetProperty("SubcategoryName"),
               Expression.Invoke(myExpression, productParam)),
           Expression.Bind(
               typeof(ResultType).GetProperty("ProductNumber"),
               Expression.Property(productParam, "ProductNumber"))),
        productParam);
    using (AdventureWorksDataContext db = new AdventureWorksDataContext())
    {
        var result = db.Products.GroupBy(groupExpr);
    }
}