While looking at some of the IOC containers listed in my last post, I noticed the user could select the lifespan of each type. So, I went back to the workbench.
I have abstracted out the lifespan from the repository, through the IRepositoryServiceProvider interface. This change also opens up the possibility for creating custom lifespans.
Usage:
var r = new Repository();
r.RegisterServiceProvider(new FactoryServiceProvider());
r.Register<IMyClass, FactoryServiceProvider>(() => new MyClass("a"));
IMyClass m = r.GetInstance<IMyClass>();
Code:
public delegate object FactoryDelegate();
public delegate T FactoryDelegate<T>();
public interface IRepositoryServiceProvider : IServiceProvider
{
void RegisterService(Type targetType, FactoryDelegate factoryMethod);
}
public class RepositoryPlusOne
{
private readonly Dictionary<Type, IRepositoryServiceProvider> providers =
new Dictionary<Type, IRepositoryServiceProvider>();
private readonly Dictionary<Type, IRepositoryServiceProvider> types =
new Dictionary<Type, IRepositoryServiceProvider>();
public void Register<T, U>(FactoryDelegate<T> factoryMethod)
where T : class
where U : IRepositoryServiceProvider
{
Type u = typeof(U);
Type t = typeof(T);
if (!providers.ContainsKey(u)) throw new ArgumentException("Unregistered Provider", "U");
providers[u].RegisterService(t, () => factoryMethod());
types.Add(t, providers[u]);
}
public void RegisterServiceProvider(IRepositoryServiceProvider provider)
{
providers.Add(provider.GetType(), provider);
}
public TService GetInstance<TService>() where TService : class
{
Type t = typeof(TService);
if (!this.factories.ContainsKey(t)) return default(TService);
return this.factories[t]() as TService;
}
}
public class FactoryServiceProvider : IRepositoryServiceProvider
{
private readonly Dictionary<Type, FactoryDelegate> factories =
new Dictionary<Type, FactoryDelegate>();
#region IRepositoryServiceProvider Members
public void RegisterService(Type targetType, FactoryDelegate factoryMethod)
{
factories.Add(targetType, factoryMethod);
}
#endregion
#region IServiceProvider Members
public object GetService(Type serviceType)
{
return (factories.ContainsKey(serviceType)) ? factories[serviceType]() : null;
}
#endregion
}
public class SingleServiceProvider : IRepositoryServiceProvider
{
private readonly Dictionary<Type, object> objects =
new Dictionary<Type, object>();
#region IRepositoryServiceProvider Members
public void RegisterService(Type targetType, FactoryDelegate factoryMethod)
{
objects.Add(targetType, factoryMethod());
}
#endregion
#region IServiceProvider Members
public object GetService(Type serviceType)
{
return (objects.ContainsKey(serviceType)) ? objects[serviceType] : null;
}
#endregion
}