从包含参数的成员表达式中提取值
本文关键字:提取 表达式 成员 包含 参数 | 更新日期: 2023-09-27 18:33:09
如何从成员表达式中提取值,其中成员表达式中的表达式不是常量,而是参数表达式。
我正在为我们公司构建一个小型的Linq to MDX ORM。
在我的生成器模板中,在数据库中找到的每个维度都是一个类,在每个维度中,都有为该维度找到的Attribute
属性。 生成所有维度类后,将生成一个更高级别Cube
类,其中包含维度作为属性以及该多维数据集的度量值。 生成所有多维数据集类后,将生成一个最终类,其中包含作为Cube<MyCube>
属性生成的多维数据集类,其中Cube<>
是我的IQueryable
类型。下面是一个示例。
//Generated cs file example:
public partial MyDatabase : CubeBase
{
//Some base implementation goes here
public Cube<FooCube> FooCube { get { return new Cube<FirstCube>(new Provider("connection string"); } }
//Any other cubes would follow here that were found on this database.
}
//A calendar dimension
public class FooCube_CalendarDimension
{
public Attribute WeekEnding { get { return new Attribute("[Calendar].[Week Ending]"); } }
public Attribute Month { get { return new Attribute("[Calendar].[Month]"); } }
public Attribute Year { get { return new Attribute("[Calendar].[Year]"); } }
}
//The "FooCube"
public partial class FooCube
{
//List Dimensions
public FooCube_Calendar_Dimension Calendar { get { return new FooCube_Calendar_Dimension(); } }
//Other dimensions here
[Measure]
public string RetailDollars { get { return "[Retail Dollars]"; } }
// Other measures here
}
现在,下面是一个用于查询多维数据集的非常基本的 linq 查询示例:
//using MyDatabase = db
var mdx = from cube in db.FooCube
where cube.Calendar.Year == "2014"
select new
{
Month = cube.Calendar.Month.Children
Dollars = cube.RetailDollars
}
例如,我正在尝试从多维数据集获取值。Calendar.Month.Children,它来自 Attribute 对象,该对象是 FooCube_Calendar_Demsion 类的属性,它本身就是"FooCube"类中的一个属性。
我尝试了访问成员表达式的值的答案,但是当它尝试编译lambda表达式时,我收到错误"未引用'cube'参数"。它传递给属性类构造函数的值存储在属性中,这就是我要访问的值(其中一个(。
基本上,你不能。 至少,不是以任何明智的方式。 目前,您所拥有的只是一个查询。 您实际上没有对象的集合,您只有有关创建这些对象需要执行的操作的信息。 查询提供程序的工作是,您当前正在编写实际生成查询定义的对象并返回它们。
您已经设计了程序,以便创建对象的查询提供程序需要已经创建对象,以便正确生成查询。 不可能已经拥有尚未生成的查询定义的对象。 您已经为自己创建了一个循环依赖项。
请务必提供在查询本身创建的对象以外的其他位置生成查询所需的信息。 通常,这是通过属性上的属性完成的,或者通过将查询基于有关类型本身的其他现有 C# 元数据来完成的。 此类型数据存在,可供查询提供程序访问,而无需您负责创建的对象的任何实际实例。
我添加这个答案是因为我找到了两种提取我想要的值的方法。我要感谢Servey的回答,因为他确实是正确的,因为我写了我的代码,所以没有以任何明智的方式这样做。
我发现有两种方法可以做到这一点。
- 将泛型
- 转换器类与泛型参数一起使用,泛型参数是我的 lambda 表达式所需的参数的类类型,然后将该泛型参数用作
Func<object, T> delgate
上的输入参数。 这是最好和最快的方法,因为在运行时没有动态操作。
var lambda = Expression.Lambda<Func<object, T>>(//Expressions here);
-
我发现的第二种方法较慢,因为它涉及
Delegate.DynamicInvoke()
方法,但它确实有效。var lambda = Expression.Lambda(member, (ParameterExpression)member.Expression); var d = lambda.Compile(); return d.DynamicInvoke(member.Expression.Type.GetConstructors()[0].Invoke(new object[0]));
这将获取对象的值,但由于动态调用而代价高昂。