我有这样的事情:
public Expression<Func<Message, bool>> FilterData()
{
switch (this.operatorEnum)
{
case FilterParameterOperatorEnum.EqualTo:
return message => !string.IsNullOrEmpty(message.Body) &&
message.Body
.Equals(this.value, StringComparison.InvariantCultureIgnoreCase);
case FilterParameterOperatorEnum.NotEqualTo:
return message => !string.IsNullOrEmpty(message.Body) &&
!message.Body
.Equals(this.value, StringComparison.InvariantCultureIgnoreCase);
case FilterParameterOperatorEnum.Contains:
return message =>
!string.IsNullOrEmpty(message.Body) &&
message.Body.IndexOf(this.value,
StringComparison.InvariantCultureIgnoreCase) >= 0;
case FilterParameterOperatorEnum.DoesNotContain:
return message =>
!string.IsNullOrEmpty(message.Body) &&
message.Body.IndexOf(this.value,
StringComparison.InvariantCultureIgnoreCase) == -1;
}
}
正如您所见,这是在Message.Body
我现在要对Message
类的其他字符串属性做同样的事情,我不想复制所有代码。
有没有办法通过以某种方式传递属性来做到这一点?
答案 0 :(得分:3)
将检索属性值的表达式Eclude到单独的lambda表达式中:
public Expression<Func<Message, bool>> FilterData(Func<Message, string> retrievePropValueFunc)
在你的过滤器表达式中,你可以调用那个新的lambda表达式(只显示一个作为例子):
return message => !string.IsNullOrEmpty(retrievePropValueFunc(message))
&& retrievePropValueFunc(message)
.Equals(this.value, StringComparison.InvariantCultureIgnoreCase);
要转到Body
媒体资源,请将message => message.Body
传递给retrievePropValueFunc
参数;如您所见,您可以修改它以传递不同的lambda表达式以便检索其他属性。
答案 1 :(得分:1)
您可以尝试完全手动编写表达式,这样您就可以将属性名称指定为字符串。这不是一个完整的解决方案,而且未经测试,但它可能会给你一个起点,看看我的意思:
var parameter = Expression.Parameter(typeof(Message), "o");
var getname = Expression.Property(parameter, "Body");
var isnullorempty = Expression.Not(Expression.Call(typeof(string), "IsNullOrEmpty", null, getname));
var compare = Expression.Equal(getname, Expression.Constant("thisvalue"));
var combined = Expression.And(isnullorempty, compare);
var lambda = Expression.Lambda(combined, parameter);
因此,您将更改函数以接受“Body”作为参数,然后将lambda最后转换为:
expression<func<Message, bool>>
我可能没有完全正确创建lambda的语法。
答案 2 :(得分:0)
只需将您的功能更改为接收属性而不是消息。
或者难以为属性名传递一个参数,并使用反射选择它。
仅针对一个选项进行编辑,而不是更改所有选项。
public Func<Message, string, bool> FilterData()
{
return (message, propName) =>
{
var prop = message.GetType().GetProperty(propName);
if(prop != null){
var propValue = (string)prop.GetValue(message,null);
return !string.IsNullOrEmpty(propValue) && ...;
}
return false;
};
}
答案 3 :(得分:0)
一种非常快速和肮脏的方法可能是enum
加上某种魔法:
public enum FilterTarget { Body, AnyOtherProp };
public Expression<Func<Message, bool>> FilterData(FilterTarget filterTarget)
{
string toBeFiltered = string.Empty;
switch(filterTarget)
{
case FilterTarget.Body :
{ toBeFiltered = message.Body; } break;
case FilterTarget.AnyOtherProp :
{ toBeFiltered = message.AnyOtherProp; } break;
default:
{
throw new ArgumentException(
string.Format("Unsupported property {0}", filterTarget.ToString()
);
}
}
switch (this.operatorEnum)
{
case FilterParameterOperatorEnum.EqualTo:
return message => !string.IsNullOrEmpty(toBeFiltered) &&
toBeFiltered.Equals(this.value, StringComparison.InvariantCultureIgnoreCase);
/* CUT: other cases are similar */
}
}
您可以使FilterData
方法更加花哨,让它接受params FilterTarget[]
,从而获得多重过滤功能(在我的头顶,不包括代码)。
用法:
var aFilterDataResult = FilterData(FilterTarget.Body);
var anotherFilterDataResult = FilterData(FilterTarget.AnyOtherProp);
...