您好,我知道这可能是重复的社区。
How to create a Expression.Lambda when a type is not known until runtime?
显然资源太多。
尽管我还是很困惑。有人可以提供下面代码中发生的情况的更清晰图片。我在下面提供了一些评论,以帮助我理解。
private Expression<Func<T, bool>> ParseParametersToFilter<T>(string parameters)
{
Expression<Func<T, bool>> finalExpression = Expression.Constant(true); //Casting error
if (string.IsNullOrEmpty(parameters))
return finalExpression;
string[] paramArray = parameters.Split(","); //parameters is one string splitted with commas
ParameterExpression argParam = Expression.Parameter(typeof(T), "viewModel"); //Expression Tree
foreach (var param in paramArray)
{
var parsedParameter = ParseParameter(param);
if (parsedParameter.operation == Operation.None)
continue; // this means we parsed incorrectly we TODO: Better way for error handling
//Property might be containment property e.g T.TClass.PropName
Expression nameProperty = Expression.Property(argParam, parsedParameter.propertyName);
//Value to filter against
var value = Expression.Constant(parsedParameter.value);
Expression comparison;
switch (parsedParameter.operation)
{ //Enum
case Operation.Equals:
comparison = Expression.Equal(nameProperty, value);
break;
//goes on for NotEquals, GreaterThan etc
}
finalExpression = Expression.Lambda(comparison, argParam);// Casting error
}
return finalExpression;
}
以上显然不起作用。
此返回到linq查询,就像IEnumerable<SomeModel>.Where(ParseParametersToFilter.Compile())
我了解我的错误是强制性错误。我该如何解决?
@@ Jeremy Lakeman回答后,我更新了代码,使其看起来像这样。尽管我使用的ViewModel非常复杂。最后,我提供了一个小预览。
private Expression<Func<T, bool>> ParseParametersToFilter<T>(string parameters)
{
Expression<Func<T, bool>> finalExpression = t => true;
if (string.IsNullOrEmpty(parameters))
return finalExpression;
string[] paramArray = parameters.Split(","); //parameters is one string splitted with commas
ParameterExpression argParam = Expression.Parameter(typeof(T), "viewModel"); //Expression Tree
Expression body = Expression.Constant(true);
foreach (var param in paramArray)
{
var parsedParameter = ParseParameter(param);
if (parsedParameter.operation == Operation.None)
continue; // this means we parsed incorrectly TODO: Better way for error handling
//Property might be containment property e.g T.TClass.PropName
Expression nameProperty = Expression.Property(argParam, parsedParameter.propertyName);
//Value to filter against
var value = Expression.Constant(parsedParameter.value);
switch (parsedParameter.operation)
{ //Enum
case Operation.Equals:
body = Expression.AndAlso(body, Expression.Equal(nameProperty, value));
break;
//goes on for NotEquals, GreaterThan etc
}
body = Expression.AndAlso(body, argParam);
}
return Expression.Lambda<Func<T, bool>>(body, argParam);
}
但是现在我得到以下异常
当我将状态作为属性参数传递时:
未为类型'model.StatusEnum'和'System.String'定义二进制运算符Equal。
当我传递User.FriendlyName参数时:
没有为类型'model.ReportViewModel'定义实例属性'User.FriendlyName'参数名称:propertyName
这是我的视图模型的样子!
public class ReportViewModel
{
public StatusEnum Status {get;set;}
public UserViewModel User {get;set;}
}
public enum StatusEnum
{
Pending,
Completed
}
public class UserViewModel
{
public string FriendlyName {get;set;}
}
"a==1,b==3"
的内容转换为viewModel => viewModel.a == 1 && viewModel.b == 3
?我认为您已经很接近了,只需要添加&&
(或||
),并始终创建一个lambda;