我需要从一个数组中读取值,该数组作为表达式提供。
我有这个方法
public ExpressionAnalizer<TModel> where TModel : class
{
public string BuildExpression(Expression<Func<TModel, bool>> expression)
{
if (expression?.Body is MethodCallExpression)
return BuildMethodCallExpression(expression);
throw new ArgumentException($"The expression '{expression?.Body}' is unsupported");
}
public string BuildMethodCallExpression(Expression<Func<TModel, bool>> expression)
{
var body = expression.Body as MethodCallExpression;
//TODO: I can't find a property that has the values of IEnumerable
return null;
}
}
并且像这样被称为
//PersonModel is a plain class with some properties.
var analizer= new ExpressionAnalizer<PersonModel>("");
var names = new List<string>() {"n1", "n2", "n3"};
//I want to get "Email contains ('n1', 'n2', 'n3')". I can read Email property, the call method name "Contains", but not itself values
var response = analizer.BuildExpression(x => names.Contains(x.Email));
有什么想法吗?我正在考虑编译表达式,但我被卡在“Closure”类上,因为System.Runtime.CompilerServices.Closure是私有的,我无法使用它。
顺便说一下,我正在使用.NET Core 1.0
修改
我需要得到一个像
这样的字符串email contains ('n1','n2','n3')
输入参数必须始终是表达式
Expression<Func<TModel, bool>>
这是因为在内部,此方法可以接收任何表达式,如
x => x.SomeProperty == "n1"
在内部,我处理表达式.Body类型,我有一个针对不同用例的实现。
我无法确定如何实现的情况是输入表达式是
var someList = new List<string>() { "string1", "anotherString", "finalString" };
someObject.SomeProperty<SomeTModel>(x => someList.Contains(x.SomeProperty))
答案 0 :(得分:1)
这是ExpressionAnalizer类的完整实现,它将为您提供所需的输出。
public class ExpressionAnalizer<TModel> where TModel : class
{
public string BuildExpression(Expression<Func<TModel, bool>> expression)
{
if (expression?.Body is MethodCallExpression)
return BuildMethodCallExpression(expression);
throw new ArgumentException($"The expression '{expression?.Body}' is unsupported");
}
public string BuildMethodCallExpression(Expression<Func<TModel, bool>> expression)
{
var body = expression.Body as MethodCallExpression;
//Get Method Name
string method = body.Method.Name;
//Get List of String Values
var methodExpression = ResolveMemberExpression(body.Object);
var listValues = ReadValue(methodExpression);
var vString = string.Format("'{0}'", string.Join("' , '", (listValues as List<string>)));
//Read Propery Name
var argExpression = ResolveMemberExpression(body.Arguments[0]);
var propertyName = argExpression.Member.Name;
return $"{propertyName} {method} ({vString})";
}
public MemberExpression ResolveMemberExpression(Expression expression)
{
if (expression is MemberExpression) return (MemberExpression)expression;
if (expression is UnaryExpression) return (MemberExpression)((UnaryExpression)expression).Operand;
throw new NotSupportedException(expression.ToString());
}
private object ReadValue(MemberExpression expression)
{
if (expression.Expression is ConstantExpression)
{
return (((ConstantExpression)expression.Expression).Value)
.GetType()
.GetField(expression.Member.Name)
.GetValue(((ConstantExpression)expression.Expression).Value);
}
if (expression.Expression is MemberExpression) return ReadValue((MemberExpression)expression.Expression);
throw new NotSupportedException(expression.ToString());
}
}
用法:
var analizer= new ExpressionAnalizer<PersonModel>();
var names = new List<string>() {"n1", "n2", "n3"};
var person = new PersonModel{ Email = "Email 1"};
var response = analizer.BuildExpression( x => names.Contains(x.Email));
响应:
Email Contains ('n1' , 'n2' , 'n3')