简体   繁体   English

动态构建表达式树

[英]Dynamically building an expression tree

I'm following this excellent example: Convert Linq to Sql Expression to Expression Tree 我正在关注这个优秀的例子: 将Linq转换为Sql表达式到表达式树

In my case I'm trying to build an expression tree where the type to be filtered is only known at run time, and is expressed as a string. 在我的情况下,我正在尝试构建一个表达式树,其中要过滤的类型仅在运行时已知,并表示为字符串。 In the above example the type Region is already known and typed directly: 在上面的示例中,类型Region已知并直接键入:

ParameterExpression pe = Expression.Parameter(typeof(Region), "region");

In my application I've been able to rewrite this as: 在我的应用程序中,我已经能够将其重写为:

ParameterExpression pe = Expression.Parameter(Type.GetType("mystring"), "listData");

My stumbling block is this from the example: 我的绊脚石就是这个例子:

MethodCallExpression whereCallExpression = Expression.Call(
            typeof(Queryable),
            "Where",
            new Type[] { query.ElementType },
            query.Expression,
            Expression.Lambda<Func<Region, bool>>(e3, new ParameterExpression[] { pe }));
var results = query.Provider.CreateQuery<Region>(whereCallExpression);

In these two lines Region is directly typed. 在这两行中, Region是直接键入的。 Is there a way of dynamically using a string "Region" to achieve the same thing? 有没有办法动态使用字符串“Region”来实现同样的事情?

Sure, but you'll have to understand the implications. 当然,但你必须了解其含义。 The type name Region is the compile time type. 类型名称Region是编译时类型。 With it, you can generate a strongly typed query. 有了它,您可以生成强类型查询。 However, since you don't have the type at compile time, you can still generate a query, but it won't be strongly typed. 但是,由于您在编译时没有该类型,您仍然可以生成查询,但不会强类型化。

You can generate an lambda expression of unknown compile time type by using the non-generic overloads. 您可以使用非泛型重载生成未知编译时类型的lambda表达式。 Likewise with the CreateQuery() method. CreateQuery()方法类似。

Here's two versions of the same query which checks if some property value matches a given value. 以下是同一查询的两个版本,用于检查某些属性值是否与给定值匹配。 One is generic and the other is not. 一个是通用的,另一个不是。

The generic version implicitly takes the type from the type of the query. 通用版本隐式地从查询类型中获取类型。

public IQueryable<TSource> PropertyEqualsValue<TSource>(IQueryable<TSource> query,
        string propertyName, object value)
{
    var param = Expression.Parameter(typeof(TSource));
    var body = Expression.Equal(
        Expression.Property(param, propertyName),
        Expression.Constant(value)
    );
    var expr = Expression.Call(
        typeof(Queryable),
        "Where",
        new[] { typeof(TSource) },
        query.Expression,
        Expression.Lambda<Func<TSource, bool>>(body, param)
    );
    return query.Provider.CreateQuery<TSource>(expr);
}
var query = PropertyEqualsValue(SomeTable, "SomeColumn", "SomeValue");

While the other the type is taken from the provided typeName . 另一种类型取自提供的typeName Note that when the query is created, we cannot provide the type, since we don't know what the type is at compile time. 请注意,在创建查询时,我们无法提供类型,因为我们在编译时不知道类型是什么。

public IQueryable PropertyEqualsValue(IQueryable query,
        Type type, string propertyName, object value)
{
    var param = Expression.Parameter(type);
    var body = Expression.Equal(
        Expression.Property(param, propertyName),
        Expression.Constant(value)
    );
    var expr = Expression.Call(
        typeof(Queryable),
        "Where",
        new[] { type },
        query.Expression,
        Expression.Lambda(body, param)
    );
    return query.Provider.CreateQuery(expr);
}
var type = Type.GetType("Some.Type.Name");
var query = PropertyEqualsValue(SomeTable, type, "SomeColumn", "SomeValue");

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM