我正在尝试使用Expression调用方法,并返回一个用于构建SQL查询的字符串。
电话很简单
var actualUsers = db.Query<UserModel>( u => u.FirstName.Contains( "ues" ) && u.LastName == "" );
在我的评估员中,我可以使用BinaryExpression评估器轻松获得"LastName = ''"
。
但是,当我尝试从MethodCalLExpression
中获取“FirstName”时,我可以使用u.FirstName
获得最接近的expression.Object.ToString();
获取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);
}
答案 0 :(得分:2)
在你的例子中:
var memberAccess = expression.Object as MemberExpression;
Console.WriteLine(memberAccess.Member.Name); //will print FirstName
MemberExpression是类,描述访问字段或属性。用它来访问属性名称。我假设您将u.FirstName.Contains( "ues" )
之类的解析后的Expresssion传递给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; }
}