创建仅定义lambda主体的表达式树

时间:2018-11-16 11:54:51

标签: c# delegates expression-trees

如标题所述-我想定义一个表达式,该表达式仅描述方法的主体。示例:

// Definition
public Expression<T> SomeExpression<T>() { ... }

// Usage
entities.Select(e => e.SomeExpression<int>())

// Instead of 
entities.Select(SomeExpression<int>())

我知道我可以将委托表达式定义为

Expression<Func<int>> SomeExpression() { ... }

但是,由于这描述了全脂委托,因此我必须将其用作.Select(SomeExpression())。这是一个问题,因为我可以无缝使用的唯一方法是在实体实例本身上附加SomeExpression

我知道这没有什么意义-简而言之,我正在尝试为项目中很久以前犯的一个愚蠢错误实施一种变通方法。正确的修复是不可能的。

备注:

  • SomeExpression必须在实体实例e中定义
  • SomeExpression必须在e上运行(我在想Expression.Consntant(this)
  • SomeExpression必须受 EntityFramework
  • 支持
  • SomeExpression必须返回通用值,例如stringint

更多信息

我正在尝试解决继承性差的问题-我有一个实体( Training ),该实体具有指向另一个实体的外键( Course )。培训实体由一个基类(同名 Training )和几个派生类( Instances )组成。问题在于,外键对于所有人来说都是绝对相同的,它被保存在派生类的属性中,而不是基类中。由于我具有公共服务层,因此每次获得 Training 实体时,我都必须对所有派生类执行几次条件转换,以获取 Course 实体

SomeExpression本身可以有效地翻译成类似的内容

t => t is InternalInstance
    ? (t as InternalInstance).Course,
    : t is OpenInstance
         ? // So on an so forth...

您可以在this topic中阅读更多详细信息。

在我的情况下,lambda为什么不起作用?为了简单起见,我在该问题中省略了泛型,但是在我的情况下,SomeExpression及其类必须依赖于几个泛型参数,因为我的解决方案中有多个Web项目,每个Web项目都有自己的课程实例类型。

这就是为什么此表达式的理想位置应该是 Training 类型的原因-它已经具有必需的通用参数。如果我不把它放在那儿,则必须创建一个服务并使用容器来解决它们。然后,我将不得不在要使用此映射的任何地方注入该服务-主要是常见的服务和视图模型。将其添加到通用服务不是问题,但是很麻烦,因为您需要附加的依赖关系才能执行映射。 视图模型存在问题,因为它们使用 AutoMapper 配置来封装映射并将其保留在内部。 AutoMapper 会在容器启动并运行之前创建并缓存地图,该解析在 NullReference 中进行。有多种方法可以提供服务运行时,但是这会增加视图模型和控制器中的样板。此时,使用表达式获取 Course 更加麻烦,然后便便了。

这就是上下文。我试图使它简短,但是有很多障碍。

0 个答案:

没有答案