While I should probably be using Dependency Injection via Ninject or a similar project, I have been attempting to implement an abstract factory design that would provide me with the following easy to read and use syntax:
UniversalFactory.Factory<IFoo>.Create<FooImpl>(... parameters ...);
I'm throwing this experiment on here in order to solicit some constructive feedback both with implementation logic and design reasoning.
Here is my current implementation:
public class UniversalFactory
{
private readonly IFactory<IFoo> FooFactoryEx;
public UniversalFactory()
{
FooFactoryEx = new FooFactory();
}
public IFactory<T> Factory<T>()
{
if (typeof (T) == typeof (IFoo))
return (IFactory<T>)FooFactoryEx;
return null;
}
}
public interface IFactory<in TF>
{
T Create<T>(params object[] p) where T : TF;
}
public class FooFactory : IFactory<IFoo>
{
public T Create<T>(params object[] p) where T : IFoo
{
if (typeof(T) == typeof(FooImpl))
{
var id = Convert.ToInt32(p[0]);
return (T)FooImpl.Create(id);
}
return default(T);
}
}
public interface IFoo
{
// Some interface
}
public class FooImpl : IFoo
{
public int Id { get; set; }
private FooImpl(int id)
{
Id = id;
}
public static IFoo Create(int id)
{
var foo = new FooImpl(id);
return foo;
}
}
This code allows a UniversalFactory to be instantiated and the following to be invoked successfully:
UniversalFactory.Factory<IFoo>().Create<FooImpl>(1);
My reasoning for this approach:
- All construction is easily identifiable via the call to UniversalFactory.
- Factories are invoked based on the interface implementation being constructed, hiding all details about the specific factory being used from the new object request.
- The object type and its construction parameters are clearly identifiable in the request.
- Object construction stays in each class, and any additional updates to other objects at construction time can take place in the factory method.
My current implementation has (at a minimum) the following flaws:
- There is no compile-time safety that ensures IFoo is implemented by an IFactory. Only that FooImpl implements IFoo is ensured.
- UniversalFactory.Factory has to add a check for every interface supported by a factory
- Individual factories have to invoke static Create() methods within each class. It would be better if the static create could be invoked in a generic way, and Create(params object[] p) somehow mapped to Create(int a, string b, ...) as needed.
Thoughts? Feedback? Is this approach unnecessary or too complex? Hopefully this experiment is, at the least, interesting to a couple of other SO folk out there.
UniversalFactory.Factory<IFoo>().Create<FooImpl>(1)
any better thannew FooImpl(1)
(assuming it was public)? \$\endgroup\$