【问题标题】:How to get Property name from MethodCallExpression?如何从 MethodCallExpression 获取属性名称?
【发布时间】:2013-10-29 01:22:32
【问题描述】:

我正在尝试使用表达式调用方法,并返回一个用于构建 sql 查询的字符串。

调用很简单

var actualUsers = db.Query<UserModel>( u => u.FirstName.Contains( "ues" ) && u.LastName == "" );

在我的评估器中,我可以使用 BinaryExpression 评估器非常轻松地获得 "LastName = ''"

但是,当我尝试从 MethodCalLExpression 中获取“名字”时,我可以通过使用 expression.Object.ToString(); 得到最接近的 u.FirstName

获取MethodCallExpression的属性名的正确方法是什么?

这是我目前掌握的方法。

    public static IList<TModel> Query<TModel> ( this IDbProvider iDbProvider, Expression<Func<TModel, object>> exp ) where TModel : class, new()
    {
        // SELECT * FROM [Users] WHERE FirstName LIKE '%ues%'
        // Should return the "Guest" user.

        var sqlExpression = GetSqlExpression( exp.Body );
        return // ....
    }

    private static string GetSqlExpression ( Expression expression )
    {
        if ( expression is MethodCallExpression )
        {
            return GetMethodCallOperator( ( MethodCallExpression )expression );
        }
        // more crap...
    }

    private static string GetMethodCallOperator ( MethodCallExpression expression )
    {
        var lambda = Expression.Lambda( expression.Arguments[0] );
        var compiledExpression = lambda.Compile().DynamicInvoke();


        var commandText = string.Empty;
        var key = expression.Object.ToString(); // "u.FirstName" -- should just be "FirstName"
        var value = compiledExpression.ToString(); // "ues"
        switch ( expression.Method.Name )
        {
            case "Contains":
                commandText = "[{0}] LIKE '%{1}%'";
                break;
        }

        // return "[FirstName] LIKE '%ues%'";
        return string.Format(commandText ,key, value);
    }

【问题讨论】:

  • 您应该访问expression.Object 以使用ExpressionVisitor 获取该值,您可以支持子表达式的所有可能值,而不是硬编码仅在那个非常有效的东西具体实例。
  • @Servy,我从来没有做过这样的事情,现在正处于一个陡峭的学习曲线上。我很想知道如何连接 ExpressionVisitor。

标签: c# lambda


【解决方案1】:

在你的例子中:

var memberAccess = expression.Object as MemberExpression;
Console.WriteLine(memberAccess.Member.Name); //will print FirstName

MemberExpression 是类,描述访问字段或属性。使用它来访问属性名称。我假设,您将解析后的表达式(如 u.FirstName.Contains( "ues" ))传递给 GetMethodCallOperator

完整示例:

void PrintName(Expression<Func<Foo, bool>> func)
{
    var methodCall = func.Body as MethodCallExpression;
    var property =  methodCall.Object as MemberExpression;
    Console.WriteLine (property.Member.Name);
}

PrintName(u => u.FirstName.Contains( "ues" )); //prints FirstName

地点:

class Foo
{
    public string FirstName { get; set; }
}

【讨论】:

  • 当然,在真正的查询提供程序中,您应该通过表达式访问者访问该表达式,而不是在该精确布局中进行硬接线。
  • @Servy 你能扩展你的评论吗?问题是What is the right way to get the property name of the MethodCallExpression?,我不是假装解决所有问题,只是一个如何从MethodCallExpression 获取属性访问名称的示例。也许我错过了什么
  • 酷,我错过了MemberExpression 位。
  • OP 正在尝试编写查询提供程序。这适用于 OP 正在使用的单个示例,但不适用于可以使用的其他类型的表达式。这样做对于查询提供者的“hello world”来说很好,但实际上并没有超越它。
  • @Servy 完全同意。
猜你喜欢
  • 1970-01-01
  • 2018-11-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-04
  • 1970-01-01
  • 1970-01-01
  • 2019-08-13
相关资源
最近更新 更多