I'm using a lot of Domain Driven Design lately and I really like it. Plus, I use a technique called inverse of control which allows dealing only with interfaces on Web applications. This is a great deal, because I'm able to use the implementation I need (Web, service or even mock-ups during development), plus it makes testing much easier.
There are a lot of third party components implementing inverse of control: Castle Windsor, StructureMap, Spring.NET, Autofac, and so on.
But since I don't like to use third party tools, I'm more inclined to use a simple version good enough for my project needs. There are several code examples on the net, like IoC container in 15 lines or IocContainer in 15 minutes.
Here is a simple version I've build, which allows the Interfaces to be automatically registered, son I don't have to write additional code or to use a configuration file. Everything is much simpler, so this is my thing.
public static class SimpleContainer
{
private static IDictionary<Type, Type> _types = null;
public static void AutoRegister()
{
if (_types == null)
{
_types = new Dictionary<Type, Type>();
Assembly assembly = Assembly.GetExecutingAssembly();
foreach (Type contractType in assembly.GetTypes())
{
if (contractType.IsInterface)
{
Type implementationType = assembly.GetType(contractType.FullName.Replace("Interfaces.I", "Implementation."));
if (implementationType != null)
_types[contractType] = implementationType;
}
}
}
}
public static void Register<TContract, TImplementation>()
{
if (_types == null) AutoRegister();
_types[typeof(TContract)] = typeof(TImplementation);
}
public static T Resolve<T>()
{
return (T)Resolve(typeof(T));
}
public static object Resolve(Type contract)
{
if (_types == null) AutoRegister();
Type implementation = _types[contract];
ConstructorInfo constructor = implementation.GetConstructors()[0];
ParameterInfo[] constructorParameters = constructor.GetParameters();
return constructorParameters.Length == 0
? Activator.CreateInstance(implementation)
: constructor.Invoke(constructorParameters.Select(parameterInfo => Resolve(parameterInfo.ParameterType)).ToArray());
}
Prety simple. The only restriction is that you have to use a naming convention for default implementations.
- Interface example: YourNamespace.Interfaces.ISomeObject
- Implementation example: YourNamespace.Implementation.SomeObject
The code to use after is really simple, a single line. No config, no extra registration lines, no nothing. Just use the resolve method and you're done.
ISomeObject someObject = Container.Resolve<ISomeObject>
Feel free to use this piece of code if it fits your needs.
No comments:
Post a Comment