Skip to content

Instantly share code, notes, and snippets.

@spearson
Created October 15, 2010 23:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save spearson/629145 to your computer and use it in GitHub Desktop.
Save spearson/629145 to your computer and use it in GitHub Desktop.
Use one implementation for all those pointless factories!
namespace xofz.Playground.Tests
{
using System;
using Xunit;
public class RedundantFactories
{
[Fact]
public void Are_used_like_this()
{
var stringFactory = new RedundantFactory<string>();
var s = stringFactory.Create('x', 15);
Console.WriteLine(s);
var subString = s.Substring(3, 7);
Console.WriteLine(subString);
}
[Fact]
public void Are_also_used_like_this()
{
var randomFactory = new RedundantFactory<Random>();
var random = randomFactory.Create();
Console.WriteLine(random.NextDouble());
}
[Fact]
public void Can_be_used_without_generics()
{
var stringFactory = new RedundantFactory(typeof(string));
var s = stringFactory.Create('x', 12);
Console.WriteLine(s);
var subString = s.Substring(3, 7); // check out that dynamic typing! w00t w00t C# 4.0!!
Console.WriteLine(subString);
}
}
}
namespace xofz.Playground
{
using System;
using System.Collections.Generic;
using System.Linq;
public class RedundantFactory<T> : RedundantFactory
{
public RedundantFactory()
: base(typeof(T))
{
}
public new T Create(params dynamic[] args)
{
return (T)base.Create(args);
}
}
public class RedundantFactory
{
public RedundantFactory(Type typeToCreate)
{
if (typeToCreate.IsAbstract || typeToCreate.IsInterface)
{
throw new ArgumentException("Type to create must be concrete");
}
this.typeToCreate = typeToCreate;
var constructors = typeToCreate.GetConstructors();
var paramSets =
constructors.Select(
constructor => constructor.GetParameters()
.Select(parameter => parameter.ParameterType)
.ToArray());
this.parameterSets = paramSets;
}
public dynamic Create(params dynamic[] args)
{
var parameterSetsWithCorrectLength = this.parameterSets.Where(parameters => parameters.Length == args.Length);
if (!parameterSetsWithCorrectLength.Any())
{
throw new ArgumentException(@"Too many or too few args", "args");
}
Type[] correctParameterSet = null;
foreach (var parameterSet in parameterSetsWithCorrectLength)
{
var parameterSetIsCorrect = true;
for (var i = 0; i < args.Length; ++i)
{
if (args[i].GetType() != parameterSet[i])
{
parameterSetIsCorrect = false;
}
}
if (!parameterSetIsCorrect)
{
continue;
}
correctParameterSet = parameterSet;
}
if (correctParameterSet == null)
{
throw new ArgumentException(@"No matching ctor could be found for args", "args");
}
return Activator.CreateInstance(this.typeToCreate, args);
}
private readonly Type typeToCreate;
private readonly IEnumerable<Type[]> parameterSets;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment