C#, Generic factory with support for private constructors

Today I got involved in a small question on Twitter on how to create a generic factory creating instances of classes having a private constructor. So I put together a small sample that shows a two solutions:

  • Using Activator (around 22s per 100000)
  • Using compiled lambdas (around 8s per 100000)

The example lets you time the difference between the solutions. And feel free to add the code using IL. Please note! This was something I put together really quick so there’s probably some room left for you to tweak.

The source code is also made availible as a Gist here: https://gist.github.com/1529618

Sample model

public interface IPerson
{
	string Name { get; set; }
}

public class Person : IPerson 
{
	public string Name { get; set; }

	private Person() { }
}

The factory

public static class Factory<T> where T : class 
{
	private static readonly Func<T> FactoryFn;

	static Factory()
	{
		//FactoryFn = CreateUsingActivator();

		FactoryFn = CreateUsingLambdas();
	}

	private static Func<T> CreateUsingActivator()
	{
		var type = typeof(T);

		Func<T> f = () => Activator.CreateInstance(type, true) as T;

		return f;
	}

	private static Func<T> CreateUsingLambdas()
	{
		var type = typeof(T);

		var ctor = type.GetConstructor(
			BindingFlags.Instance | BindingFlags.CreateInstance |
			BindingFlags.NonPublic,
			null, new Type[] { }, null);

		var ctorExpression = Expression.New(ctor);
		return Expression.Lambda<Func<T>>(ctorExpression).Compile();
	}

	public static T Create(Action<T> init)
	{
		var instance = FactoryFn();

		init(instance);

		return instance;
	}
}

The test app

class Program
{
    static void Main(string[] args)
    {
		//TOUCH ONCE BEFORE TIMING
		var touchedPerson = Factory<Person>.Create(p => p.Name = "Daniel");

		for (var a = 0; a < 5; a++)
		{
			var sw = Stopwatch.StartNew();
			for (int c = 0; c < 100000; c++)
			{
				var person = Factory<Person>.Create(p => p.Name = "Daniel");
				var n = person.Name;
			}
			sw.Stop();
			Console.WriteLine(sw.Elapsed.TotalMilliseconds);
		}
		Console.ReadKey();
    }
}

That’s it. Enjoy!

//Daniel

About these ads

6 thoughts on “C#, Generic factory with support for private constructors

  1. Pingback: DotNetShoutout

  2. Pingback: Interesting .NET Links - December 30 , 2011 | Tech Blog

  3. I don’t understand why you would want to be able to instantiate from private constructors. There’s generally a reason for creating a constructor as private, that being that you don’t want it to be called.

    • Not my call, I just provided a solution, but right of my head….

      E.g in a deserialization/mapping scenario. Normal consumers should not be “allowed” to use a certain constructor, whilst your tooling that perhaps create an instance and the populate certain members on it.

      //Daniel

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