Return expression <> using various class properties

I have something like this:

 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; } } 

As you can see, this is done on Message.Body

Now I have to do the same in the other string properties of the Message class, and I don't want to duplicate all this code.

Is there a way to do this by passing the property in some way?

+6
source share
4 answers

You can try to make the expression completely manually, which will give you the opportunity to specify the name of the property as a string. This is not a complete solution and it has not been tested, but it can give you a starting point to understand what I mean:

 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); 

So, you would change your function to take Body as a parameter, and then drop the lambda at the end:

 expression<func<Message, bool>> 

Maybe I don't have the syntax to create lambda for sure.

+1
source

Eclude expression that returns the value of the property in a separate lambda expression:

 public Expression<Func<Message, bool>> FilterData(Func<Message, string> retrievePropValueFunc) 

In filter expressions, you can invoke this new lambda expression (just by showing one example):

 return message => !string.IsNullOrEmpty(retrievePropValueFunc(message)) && retrievePropValueFunc(message) .Equals(this.value, StringComparison.InvariantCultureIgnoreCase); 

To go to the Body property, pass message => message.Body to the retrievePropValueFunc parameter; as you can see, you can change this to pass various lambda expressions to look for other properties.

+3
source

Just change your function to get a property instead of a message.

Or the hard path passes another parameter to the property name and selects it using reflection.

Edit only one option than change for all options.

  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; }; } 
0
source

A very quick and dirty approach could be enum plus some kind of magic:

 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 */ } } 

You can make the FilterData method even more bizarre by letting it accept params FilterTarget[] , thereby gaining multi- params FilterTarget[] capabilities (from the top of the head, the code is not included).

Using:

 var aFilterDataResult = FilterData(FilterTarget.Body); var anotherFilterDataResult = FilterData(FilterTarget.AnyOtherProp); ... 
0
source

Source: https://habr.com/ru/post/945484/


All Articles