C#如何转换表达式<;Func<;SomeType>&燃气轮机;对一个表达式<;Func<;其他类型>&燃气轮机;
我以前使用过基于lamdas的C#表达式,但我没有手工编写它们的经验。给定一个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中。我希望将表达式传递到存储库(作为规范的一种形式),但它们应该基于模型实体。但是我无法将这些表
表达式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方法附加表…响应在本主题中: