What you basically implemented is a small IoC container that is able to auto-wire object graphs. But your implementation is only able to create object graphs of concrete objects. This makes your code violate the Dependency Inversion Principle.
What's missing from the implementation is some sort of Register
method that tells your AutomaticFactory
that when confronted with an abstraction, it should resolve the registered implementation. That could look as follows:
private static readonly Dictionary<Type, Type> registrations =
new Dictionary<Type, Type>();
public static void Register<TService, TImplementation>()
where TImplementation : class, TService
where TService : class
{
registrations.Add(typeof(TService), typeof(TImplementation));
}
No you will have to do an adjustment to the GetOne
method as well. You can add the following code at the start of the GetOne
method:
if (registrations.ContainsKey(type))
{
type = registrations[type];
}
That will ensure that if the supplied type
is registered in the AutomaticFactory
as TService
, the mapped TImplementation
will be used and the factory will continue using this implementation as the type to build up.
This does mean however that you now have to explicitly register the mapping between IClock
and SystemClock
(which is a quite natural thing to do if you're working with an IoC container). You must make this mapping before the first instance is resolved from the AutomaticFactory
. So you should add the following line to to the beginning of the Main
method:
AutomaticFactory.Register<IClock, SystemClock>();