Click here to Skip to main content
11,410,118 members (63,745 online)
Click here to Skip to main content

Factory Method Pattern With Expression Trees using C#

, 14 May 2012 CPOL
Rate this:
Please Sign up or sign in to vote.
Efficient Factory Method Pattern Implementation in C# using Expression Trees

Introduction  

Well, the sole purpose of writing this article is not to tell you what a factory class or factory method pattern is.

I am sure there are better known articles already published in web space.

On the contrary, I am trying to tell you a new efficient way to implement the factory class using Expression trees rather than using Reflection. 

Background          

Try To Read About Factory Method Pattern Implementation using C#.  

Here is an article to help you kick start with:-  

http://www.codeproject.com/Articles/9319/Creating-a-Class-Factory-with-C-and-NET 

Using the code   

OK, so let’s understand how to create an object using Factory method pattern by using Reflection first. 

Here is our sample factory class diagram:- 

Well to make a simple Reflection based Factory Class for creating our shirt type on the basis of type name, here is what is required:-

  1. Create a Dictionary with Shirt Type Name [String] as key and Shirt Type [Type] as value.   

  2. User Activator (System. Activator) to create an instance of Type for the supplied shirt type name. 

Below is the code:- 

public Shirt CreateShirt(string shirtType, Color color, string brand)
{
if (!_types.ContainsKey(shirtType)) 
    return null;

var t = _types[shirtType];
return Activator.CreateInstance(t, color, brand) as Shirt;
}

Problem with System Activator: 

Well you might be wondering what is wrong with the above code, let me tell you how Activator’s CreateInstance works or rather actually creates an instance to understand why it is slow and need to be replaced. 

Here is the definition of CreateInstance Method:- 

public static object CreateInstance(Type type, params object[] args);

The first parameter is the type you want the activator to create an object. Internally, the activator will search this type from its name in metadata.   

Next argument is object array with params keyword, which means you can supply parameters without making an array. 

Internally, activator will try to search for a constructor in the type whose parameters match in number, order, and type with the arguments supplied in the form of object array to CreateInstance method.  

If args array is an empty array or null, the constructor that takes no parameters (the default constructor) is invoked. 

Now because it is searching through the type using Reflection, which internally always searches on strings, it turns out to be slow at run-time. 

For the above shirt factory, it took around 4.74 seconds on my Core 2 Duo, 4GB Ram Machine, when I ran the CreateShirt Method for a million times. 

sysActFactory.CreateShirt("Tee", Color.Blue, "Reebok");

Now Let’s see what is the fix

Expression Trees Come To Rescue  

OK, so how does Expression Trees help in this scenario?  

If you try to dissect activator’s CreateInstance method, you will notice that it’s the metadata search that it has to do every time before invoking the object, that makes it slow. 

So I decided, that if somehow I can replace this search through metadata my making expressions at compile time, I will be left with only invoking the expression at runtime. 

Well, it was easy, why not supply the right constructor at compile time and then make an Expression out of it. We can then call this expression at runtime, which will be much like invoking the constructor directly. 

Make sense? Let’s see… 

Let’s start by having our custom Activator delegate with the same signature as CreateInstance.

public delegate object Activator(params object[] args);

We will use this delegate to convert our expression to and return from our Activator Creation Method.

Here is how the method looks like:-

       
        private static TDelegate DoGetActivator<TDelegate>(ConstructorInfo ctor)  
        where TDelegate : class
        {
            var ctorParams = ctor.GetParameters();
            var paramExp = Expression.Parameter(typeof (object[]), "args");

            var expArr = new Expression[ctorParams.Length];

            for (var i = 0; i < ctorParams.Length; i++)
            {
                var ctorType = ctorParams[i].ParameterType;
                var argExp = Expression.ArrayIndex(paramExp, Expression.Constant(i));
                var argExpConverted = Expression.Convert(argExp, ctorType);
                expArr[i] = argExpConverted;
            }

            var newExp = Expression.New(ctor, expArr);
            var lambda = Expression.Lambda<TDelegate>(newExp, paramExp);            
            return lambda.Compile();
        }

Next you can simple wrap it up in an extension method and replace the TDelegate Type With Activator Type.  

Here is how it looks like:- 

public static Activator GetActivator(this ConstructorInfo ctor)
{
   return DoGetActivator<Activator>(ctor);
}

You can have another extension of Type that looks like this:-

public static Activator GetActivator(this Type type)
        {
            var ci = type.GetConstructors(BindingFlags.Instance |BindingFlags.Public).FirstOrDefault();

            return ci.GetActivator();
        }

We can also create another extension to Activator Type to actually call the Constructor, like this:-

public static T CreateInstance<T>(this Activator activator, params object[] args) where T : class
        {
            return activator(args) as T;
        }

Here is how to call the above set of methods to create an instance of PartyWear Shirt:- 

var type = typeof (PartyWear);
var activator = type.GetActivator();

var shirt = activator.CreateInstance<Shirt>(Color.Blue, "Blackberry");

Now, let’s run the litmus test.  

We will make two factories one with System Activator and the other one with Expression Tree Activator and see the difference:- 

 

Well, well, well, you can see the difference.

The one with expression trees took less than half a second to make a million Tee Shirts where as system Activator took a whopping 4.7 seconds.

So that’s it Folks, Download the code attached and play with it.

Happy Programming!!! 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

BuggyCoder
Technical Lead
India India
Lead Developer, working on .net platform for over 6.5 years with specialization in writing Telecom Software.

Have working experience in writing Entity Services using Domain Driven Design and RAD design paradigms.

A Microsoft Certified Professional Developer on .net Framework 3.5...

A programmer at heart, Love to spend time watching sci-fi movies, reading new technologies, and helping my community with whatever skill-set and knowledge i possess.

Comments and Discussions

 
GeneralMy vote of 3 PinmemberKlaus Luedenscheidt14-May-12 20:02 
GeneralRe: My vote of 3 PinmemberBuggyCoder14-May-12 21:15 
QuestionHelper methods... PinmvpPaulo Zemek14-May-12 6:05 
AnswerRe: Helper methods... PinmemberBuggyCoder14-May-12 9:34 
QuestionThere are other more elaborate articles around on this topic PinmemberAndreas Gieriet14-May-12 0:38 
AnswerRe: There are other more elaborate articles around on this topic PinmemberBuggyCoder14-May-12 1:08 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.150414.5 | Last Updated 14 May 2012
Article Copyright 2012 by BuggyCoder
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid