C# Dynamic Function Factory

Building functions instead of expression trees.

The functional programming features of the latest versions of C# allow developers to harness a very expressive programming paradigm to solve challenges in new, elegant ways. Two of the very interesting new features are the “Func<>” delegate and the Lamda expression.

A Lamda expression is a simple expression that is interpreted by the compiler as either a delegate or an expression tree, depending on the Type called for in the given context. You see them used often in LINQ. For example:

   1:  var bostonPeople = people.Where( p => p.City == "Boston" );

Some time has been devoted in explaining how a LINQ query like the above can be created dynamically by building expression trees (see the excellent article: Creating Dynamic Queries in LINQ by Bill Wagner). While this approach to creating a Lambda expression dynamically is very powerful, some may find that it is far more than they need and instead could get by with a simpler implementation. Others may find it difficult to read or understand and therefore provides a challenge in maintenance.

One possible solution is to use the powerful new Func<> and a lambda expression to easily create a function on the fly. This solution is not quite as powerful as building an expression tree but in situations where it’s possible it will save quite a bit of code.

To demonstrate, how about a completely contrived example. Let’s say you have this object in your domain:

   1:  class Person
   2:  {
   3:      public string Name { get; set; }
   4:      public string City { get; set; }
   5:      public string State { get; set; }
   6:  }

and then let’s assume you need to have a way to return back a subset of a collection of “people” based on some criteria that won’t be known until runtime. We can create a factory that builds a function on the fly that we can pass into a LINQ method. Essentially what the “BuildEqFuncFor<T>” method does is build a Func<T, bool> that compares a given value against a named property of T. The signature of the built function is compatible with most LINQ query parameter expectations. (Please excuse the code formatting and naming conventions – I’m trying to fit it into this post.)

   1:  class FunctionFactory
   2:  {
   3:      public static Func<T, bool> BuildEqFuncFor<T>
   4:          (string prop, object val)
   5:      {
   6:          return t => t.GetType()
   7:              .InvokeMember(prop, 
   8:                  BindingFlags.GetProperty, 
   9:                  null, 
  10:                  t, 
  11:                  null) == val;
  12:      }
  13:  }

Now this factory only supports building functions that test for equivalency between some property of some object and a value, however more advanced functions could be constructed using the same concept.

We can now use this FunctionFactory to create a function on the fly and use it in a LINQ method to query our people collection. Let’s see what that looks like:

   1:  var personIsFromBoston = 
   2:      FunctionFactory.BuildEqFuncFor<Person>("City", "Boston");
   3:   
   4:  var bostonPeople = people.Where( personIsFromBoston );
   5:   
   6:  if (bostonPeople.Any())
   7:      bostonPeople.ToList().ForEach(p => Console.WriteLine(p.Name));

Obviously this is a simple example but it could easily be expanded upon (and optimized) to create a more advanced function factory that could generate functions to solve problems beyond just creating dynamic LINQ queries. An issue you should take into account, is there is no compile time type checking so you should take care to handle cases where the type of the property doesn’t match the type of the value, or that the property even exists on the type provided at all.

As an interesting aside… this could be made even a bit more flexible by adding another function layer:

   1:  Func<string, Func<Person, bool>> personIsFrom =
   2:      s => FunctionFactory.BuildEqFuncFor<Person>("City", s);
   3:   
   4:  var bostonPeople = people.Where( personIsFrom("Boston") );

I hope you found this interesting, I look forward to your comments.

Published Monday, February 23, 2009 1:36 AM by fdumlao

Comments

# re: C# Dynamic Function Factory

Monday, February 23, 2009 8:59 AM by Joe Chung

Here's a more efficient way to do that using LINQ Expressions (System.Linq.Expression):

public static Func<T, bool> BuildEqFuncFor2<T>(string prop, object val)

{

   var o = Expression.Parameter(typeof(T), "t");

   Expression<Func<T, bool>> expression = Expression.Lambda<Func<T, bool>>(Expression.Equal(Expression.PropertyOrField(o, prop), Expression.Constant(val)), o);

   return expression.Compile();

}

# re: C# Dynamic Function Factory

Monday, February 23, 2009 9:45 AM by fdumlao

@Joe Chung

I linked to an article that demonstrates how to use System.Linq.Expressions - which has been the way we have been doing this for a while.

The point of my post was to provide an alternative: Building functions INSTEAD of building expression trees. By doing this you get a much more succinct syntax that more clearly expresses what you want to do, instead of how you want it to be done.

Also, I am not certain that building an expression tree can be considered more efficient. I think it would be an interesting thing to benchmark.

# re: C# Dynamic Function Factory

Monday, February 23, 2009 5:03 PM by Joe Chung

I benchmarked this code and found it faster (up to two times faster).  I wouldn't have said that it's more efficient otherwise.

I disagree that your implementation more clearly expresses what you want to do.  It may be more succinct in the way that magic constants but only because the LINQ expression API is unnecessarily verbose.

Anyways, when the CLR gets true metaprogramming support [Anders Hejlsberg, Future of C#, PDC 2008], both our approaches will be obsolete.

# Building Functions vs. Building Expressions: Performance Comparison

Tuesday, February 24, 2009 7:09 AM by i have a framework...

Yesterday I posted an entry describing a method for building functions as opposed to building expressions

# re: C# Dynamic Function Factory

Tuesday, February 24, 2009 7:13 AM by fdumlao

@Joe Chung

I'm not sure what benchmarks you were using - but in my experience compiling expressions on the fly has not been "efficient". After reading your comment that it was "twice" as efficient I felt compelled to do my own benchmarks. As it turns out building expressions is much much slower than building functions. See:

weblogs.asp.net/.../building-functions-vs-building-expressions-performance-comparison.aspx

# re: C# Dynamic Function Factory

Tuesday, February 24, 2009 2:32 PM by Dig

Oh Snap, Joe! You just got C#-served! I'd sure love to see the EXPRESSION on your face now!!

# re: C# Dynamic Function Factory

Friday, April 24, 2009 11:38 AM by Wyatt

Nice comparing, I dig it further in more general way:

# re: C# Dynamic Function Factory

Friday, April 24, 2009 3:41 PM by Wyatt

please see this link www.cnblogs.com/.../1443251.html, and appreciate your guys' comments.

# re: C# Dynamic Function Factory

Friday, April 24, 2009 3:55 PM by wyatt

Simply speaking, if you change the type of property of Person, can building function factory stil work without any improvement?

Happy coding.

Wyatt

# i have a framework&#8230; &raquo; Blog Archive &raquo; Building Functions vs. Building Expressions: Performance Comparison

Pingback from  i have a framework&#8230;  &raquo; Blog Archive   &raquo; Building Functions vs. Building Expressions: Performance Comparison

Leave a Comment

(required) 
(required) 
(optional)
(required)