Expression API Messabout

I have been using the Expression namespace in .NET for a while now, and at times it is truly useful, but whenever I look at it, I am always confused and wonder how to start with it. To this end I have decided to start this cheat sheet page, which shows how to do simple tasks using the Expression namespace. I will be adding to this over time.

Create a Delegate To Call A Method

This simple one creates a delegate that accepts an object argument, casts it to some type and calls a method on it, and returns the value from the delegate

If we were to do this with hardcoded code it would be something like this

(Object x) =>
{
 String target = x as String;
 return target.GetEnumerator();
}
string testString = "madness";
MethodInfo methInfo = typeof(string).GetMethod("GetEnumerator");
ParameterExpression param = Expression.Parameter(typeof(object), "target");

UnaryExpression cast = Expression.ConvertChecked(param, typeof(string));
Expression call = Expression.Call(cast, methInfo);
Func<object, CharEnumerator> executeAction = Expression.Lambda<Func<object, CharEnumerator>>(call, param).Compile();

//test it out
CharEnumerator enumerator = executeAction(testString);
while (enumerator.MoveNext())
{
Console.Write(enumerator.Current);
}

Running this code the output that I see in the Console is “madness”

Dynamic Where Clause

I often find that I have to build up a dynamic Where clause, and you either have to have lots of if/then else statements to build up pre-canned Func<T,TResult> or get clever with Expression Trees.

Suppose I have a simple Person class something like this

public class Person
{
 public string FirstName { get; set; }
 public string LastName { get; set; }

public Person(string firstName, string lastName)
 {
 this.FirstName = firstName;
 this.LastName = lastName;
 }

public override string ToString()
 {
 return String.Format("FirstName {0}, LastName {1}", FirstName, LastName);
 }
}

And that I wish to conduct the following dynamic filter on it at runtime

  • Find all Person objects that have a 1st name starting with “Ch”

If we were to do this with hardcoded code it would be something like this

people.Where(x=> x.FirstName.StartsWith("Ch");

Here some code that does that

List<Person> people = new List<Person>();
people.Add(new Person("Bert", "Adams"));
people.Add(new Person("Bradley", "Lones"));
people.Add(new Person("Charley", "Chalk"));

string propertyNameToSearchBy = "FirstName";
string searchType = "StartsWith";
string searchValue = "Ch";

var paramStart = Expression.Parameter(typeof(Person), "x");
Expression<Func<Person, bool>> func = Expression.Lambda<Func<Person, bool>>(
 Expression.Call(Expression.Property(paramStart,
 typeof(Person).GetProperty(propertyNameToSearchBy).GetGetMethod()),
 typeof(String).GetMethod(searchType.ToString(), new Type[] { typeof(String) }),
 new Expression[] { Expression.Constant(searchValue, typeof(string)) }),
 new ParameterExpression[] { paramStart });

Func<Person, bool> funcComp = func.Compile();

//test it out
foreach (Person person in people.Where(funcComp))
{
 Console.WriteLine(person);
}
Console.ReadLine();

Running this code the output that I see in the Console is “FirstName Charley LastName Chalk”

This is an uber simple example, but the important thing to note in there is that you can create a Where filter on the fly and those filter values could  come from the user through a UI or the database, so we could potentially create quite a few distinct Where filters using that one bit of code. The alternative would be to have loads of pre-canned delegates one for FirstName StartsWith filter, one for LastName StartsWith filter, using this method you can just fill in the values and let this delegate do its work.

Getting A Property Value From An Object

This is another convenient one, which simply grabs the value of a property from a source object. I will use the same “Person” object we just used

If we were to do this with hardcoded code it would be something like this

Person p = New Person("Bert", "Adams");
string thePersonsFirstName = (string)p.GetType().GetProperty("Person").GetValue(p, null);

So lets looks for a generic method that will work for us, ok this example Reflection would work to since its all based around magic strings

class Program
{
 static void Main(string[] args)
 {
 Person p = new Person("Bert", "Adams");

Console.WriteLine(GetValue<Person, string>(p, "FirstName"));
 Console.ReadLine();

}
 public static TResult GetValue<T, TResult>(T incoming, string propertyName)
 {
 PropertyInfo property = typeof(T).GetProperty(propertyName);
 ParameterExpression param = Expression.Parameter(typeof(T), "x");
 Expression propertyAccess = Expression.Property(param, property);
 Expression convert = Expression.Convert(propertyAccess, typeof(object));
 Func<T, object> lambda =
 Expression.Lambda<Func<T, object>>(convert, param).Compile();
 return (TResult)lambda(incoming);
 }
 public class Person
 {
 public string FirstName { get; set; }
 public string LastName { get; set; }

public Person(string firstName, string lastName)
 {
 this.FirstName = firstName;
 this.LastName = lastName;
 }

public override string ToString()
 {
 return String.Format("FirstName {0}, LastName {1}", FirstName, LastName);
 }
 }
}

Running this code the output that I see in the Console is “Bert”

Get A Property Value

Say you had this class and you wanted to grab the SomeString value

public class SomeType
{
  public static string SomeString
  {
    get { return “I am a string” }
  }
}

We could just make a small Lambda like this

var exp = Expression.Lambda<Func<string>>(
                Expression.Property(null, typeof(SomeType), “SomeString”));

return exp.Compile();

Other Sources

I also wrote a dedicated article on Expression API recipes with a cool american chap (Ian you know who you are). This article covered the following things

Here is a list of the scenarios we will be covering

  • Change tracker
  • Convert
  • Generic object HashCode computation
  • If-Then-Else
  • Property get/set
  • Dynamic where

Want to know more please read the full article over here

http://www.codeproject.com/Articles/651464/Expression-API-Cookbook

 

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: