Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/307.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#如何转换表达式<;Func<;SomeType>&燃气轮机;对一个表达式<;Func<;其他类型>&燃气轮机;_C#_Linq To Sql_Lambda_Repository Pattern_Expression Trees - Fatal编程技术网

C#如何转换表达式<;Func<;SomeType>&燃气轮机;对一个表达式<;Func<;其他类型>&燃气轮机;

C#如何转换表达式<;Func<;SomeType>&燃气轮机;对一个表达式<;Func<;其他类型>&燃气轮机;,c#,linq-to-sql,lambda,repository-pattern,expression-trees,C#,Linq To Sql,Lambda,Repository Pattern,Expression Trees,我以前使用过基于lamdas的C#表达式,但我没有手工编写它们的经验。给定一个表达式originalPredicate,我想创建一个表达式translatedPredicate 在本例中,SomeType和OtherType具有相同的字段,但它们不相关(没有继承,也不基于公共接口) 背景:我有一个基于LINQtoSQL的存储库实现。我将LINQ到SQL实体投影到我的模型实体,以使我的模型保持在POCO中。我希望将表达式传递到存储库(作为规范的一种形式),但它们应该基于模型实体。但是我无法将这些表

我以前使用过基于lamdas的C#表达式,但我没有手工编写它们的经验。给定一个
表达式originalPredicate
,我想创建一个
表达式translatedPredicate

在本例中,SomeType和OtherType具有相同的字段,但它们不相关(没有继承,也不基于公共接口)


背景:我有一个基于LINQtoSQL的存储库实现。我将LINQ到SQL实体投影到我的模型实体,以使我的模型保持在POCO中。我希望将表达式传递到存储库(作为规范的一种形式),但它们应该基于模型实体。但是我无法将这些表达式传递到数据上下文,因为它需要基于LINQ到SQL实体的表达式。

没有隐式的转换方法。必须将现有委托包装在lambda中,该lambda将根据参数类型创建新类型:

var translatedPredicate = x => originalPredicate(OtherTypeFromSomeType(x))

其中
OtherTypeFromSomeType
SomeType
参数创建
OtherType
实例。

对于
表达式
,最简单的方法是转换表达式

class Foo {
    public int Value { get; set; }
}
class Bar {
    public int Value { get; set; }
}
static class Program {
    static void Main() {
        Expression<Func<Foo, bool>> predicate =
            x => x.Value % 2 == 0;
        Expression<Func<Bar, Foo>> convert =
            bar => new Foo { Value = bar.Value };

        var param = Expression.Parameter(typeof(Bar), "bar");
        var body = Expression.Invoke(predicate,
              Expression.Invoke(convert, param));
        var lambda = Expression.Lambda<Func<Bar, bool>>(body, param);

        // test with LINQ-to-Objects for simplicity
        var func = lambda.Compile();
        bool withOdd = func(new Bar { Value = 7 }),
             withEven = func(new Bar { Value = 12 });
    }
}
class-Foo{
公共int值{get;set;}
}
分类栏{
公共int值{get;set;}
}
静态类程序{
静态void Main(){
表达式谓词=
x=>x。值%2==0;
表达式转换=
bar=>newfoo{Value=bar.Value};
var param=表达式参数(类型为(Bar),“Bar”);
var body=Expression.Invoke(谓词,
Invoke(convert,param));
var lambda=表达式.lambda(body,param);
//为了简单起见,使用LINQ to对象进行测试
var func=lambda.Compile();
bool with奇数=func(新条{Value=7}),
With偶数=func(新条{Value=12});
}
}
但是请注意,不同的提供商将以不同的方式支持这一点。例如,EF可能不喜欢它,即使LINQtoSQL也不喜欢


另一个选项是完全重建表达式树,使用反射查找相应的成员。要复杂得多。

我找到了另一种方法,也包括包装原始代理

Func<T, object> ExpressionConversion<U>(Expression<Func<T, U>> expression)
{
    Expression<Func<T, object>> g = obj => expression.Compile().Invoke(obj);
    return g.Compile();
}
Func表达式转换(表达式)
{
表达式g=obj=>Expression.Compile().Invoke(obj);
返回g.Compile();
}

我和你有同样的问题,我用EF解决了这个问题:

var viewModeValue = dbContext.Model.Select(m => new ViewModel{Field = m.Field}).Where(predicate) //predicate is an Expression<Func<ViewModel, bool>>
var viewModeValue=dbContext.Model.Select(m=>newviewmodel{Field=m.Field})。其中(谓词)//谓词是一个表达式

实体框架知道如何构建正确的sql命令。转换表达式要复杂得多,因为它是为不可变而构建的,如果您做错了什么,可能会导致不希望的运行时效果,至少在我的情况下,它是不需要的

问题是关于表达,而不是代表。不能使用此方法调用子表达式;它更复杂。哎呀,读得不够仔细。无论如何,技术基本上是一样的,表达式只需要做更多的工作(即使从技术上讲,我的代码在第一次编译
originalPredicate
,并使用
Expression
而不是
var
;-)之后仍然可以工作)).我希望L2EF喜欢这样,因为我正在将表达式从接口转换为具体类,并将结果作为IQueryable返回。。。你认为有办法减少开销吗?+1:这让我走上了我认为正确的道路。尽管如此,我确实学到了一些新东西。我从英孚那里得到了一份缺失的关系。在我提出一个新问题之前,我会再做一点。我想知道是否需要通过EntityCollection方法附加表…响应在本主题中: