Reputation: 139
I am new to using expressions and I am having some problems in an example I am working through.
What I am trying to achieve is to create an Expression which has 2 (or many) Expressions within.
For example:
public static Expression<Func<Occurrence, bool>> ReporterStartsWithAndClosed()
{
ParameterExpression occPar = Expression.Parameter(typeof(Occurrence));
MemberExpression recorderProp = Expression.Property(occPar, "Reporter");
MemberExpression fullnameProp = Expression.Property(recorderProp, "FullName");
ConstantExpression letter = Expression.Constant("A", typeof(string));
MethodInfo miStartsWith = typeof(string).GetMethod("StartsWith", new[] { typeof(string) });
MethodCallExpression mCall = Expression.Call(fullnameProp, miStartsWith, letter);
MemberExpression oiProp = Expression.Property(occPar, "OccurrenceIncident");
MemberExpression statusProp = Expression.Property(oiProp, "OccurreceIncidentStatus");
MemberExpression nameProp = Expression.Property(statusProp, "Name");
ConstantExpression name = Expression.Constant("Closed", typeof(string));
BinaryExpression equalTo = Expression.Equal(name, nameProp);
return ...?
}
The question I have, is how to I combine these expressions to return the correct type for this method. I.e. what is the syntax for combining the logic for mCall and equalTo Expressions.
My initial thought were that I should be using BlockExpressions but I couldn't get this to work.
Any help would be greatly appreciated.
Thanks David
Upvotes: 1
Views: 182
Reputation: 134841
So to do a logical AND, use the AndAlso()
method to generate the expression. Then to finish off your method, you'll want to put this combined method into an lambda expression.
Just some hints, I'd avoid writing out the types in your declarations, it makes everything harder to read. Also, you could call a method by name by using this overload of Call()
so no need to get the MethodInfo
object for the method.
I'd put it together like this (untested):
public static Expression<Func<Occurrence, bool>> ReporterStartsWithAndClosed(
string letter = "A")
{
// occurrence =>
// occurrence.Reporter.FullName.StartsWith("A")
//
// occurrence.OccurrenceIncident.OccurrenceIncidentStatus.Name == "Closed"
var occurrence = Expression.Parameter(typeof(Occurrence), "occurrence");
var reporter = Expression.Property(occurrence, "Reporter");
var fullName = Expression.Property(reporter, "FullName");
var startsWithLetter = Expression.Call(
fullName,
"StartsWith",
null,
Expression.Constant(letter, typeof(string))
);
var incident = Expression.Property(occurrence, "OccurrenceIncident");
var status = Expression.Property(incident, "OccurrenceIncidentStatus");
var name = Expression.Property(status, "Name");
var equalsClosed = Expression.Equal(
name,
Expression.Constant("Closed", typeof(string))
);
var body = Expression.AndAlso(startsWithLetter, equalsClosed);
return Expression.Lambda<Func<Occurrence, bool>>(body, occurrence);
}
Upvotes: 1