Smooth.IoC.Dapper.Repository.UnitOfWork
Smooth.IoC.Dapper.Repository.UnitOfWork copied to clipboard
Implemented repository factory
Implemented repository factory and provided unity example for usage in readme
Example usage:
var person = await uow.GetRepository<IPersonRepository>().GetPersonDetailsAsync(id);
I've kept the IOC abstract like you have, just haven't provided an example implementation of each, sadly I'm using unity so I had a specific example but you could simply do the same e.g. Autofac would be:
public class AutofacRegistrar
{
public void Register(ContainerBuilder builder)
{
builder.Register(c=> new AutofacDbFactory(c.Resolve<IComponentContext>())).As<IDbFactory>().SingleInstance();
builder.Register(c=> new AutofacRepositoryFactory(c.Resolve<IComponentContext>())).As<IRepositoryFactory>().SingleInstance();
builder.RegisterType<Dapper.Repository.UnitOfWork.Data.UnitOfWork>().As<IUnitOfWork>();
}
sealed class AutofacDbFactory : IDbFactory
{
private readonly IComponentContext _container;
public AutofacDbFactory(IComponentContext container)
{
_container = container;
}
public T Create<T>() where T : class, ISession
{
return _container.Resolve<T>();
}
public TUnitOfWork Create<TUnitOfWork, TSession>(IsolationLevel isolationLevel = IsolationLevel.Serializable) where TUnitOfWork : class, IUnitOfWork where TSession : class, ISession
{
return _container.Resolve<TUnitOfWork>(
new ParameterOverride("factory", _container.Resolve<IDbFactory>()),
new ParameterOverride("repositoryFactory", _container.Resolve<IRepositoryFactory>()),
new ParameterOverride("session", Create<TSession>()),
new ParameterOverride("isolationLevel", isolationLevel),
new ParameterOverride("sessionOnlyForThisUnitOfWork", true));
}
public T Create<T>(IDbFactory factory, IRepositoryFactory repositoryFactory, ISession session, IsolationLevel isolationLevel = IsolationLevel.Serializable) where T : class, IUnitOfWork
{
return _container.Resolve<T>(
new ParameterOverride("factory", factory),
new ParameterOverride("repositoryFactory", repositoryFactory),
new ParameterOverride("session", session),
new ParameterOverride("isolationLevel", isolationLevel),
new ParameterOverride("sessionOnlyForThisUnitOfWork", false));
}
public void Release(IDisposable instance)
{
instance.Dispose();
}
}
sealed class AutofacRepositoryFactory : IRepositoryFactory
{
private readonly IComponentContext _container;
public AutofacDbFactory(IComponentContext container)
{
_container = container;
}
public TRepository GetRepository<TRepository>(IUnitOfWork uow) where TRepository : IRepository
{
return _container.Resolve<TRepository>(
new ParameterOverride("uow", uow)
);
}
}
}
Just trying something out, to see if I can't just inject the repository factory just in to the unit of work, which would decouple it from session...
Ok, so yes you can decouple the repository factory from the session and it still works with the unit of work. I've update the PR.
@mcinnes01 Thanks !:-) I need to have and deeper look at this. We also need to think about the disposal of the repos, e.g.windsor needs you to dispose factory created items as it does not track it (unless Singleton).
Please give me a little time. Have a good evening...
Hi @mcinnes01 Sorry for the long wait. I have been Working days and nights these days :-). Uat busy you know...
If you look under the test examples with IOC installeres you can e.g. see that Autofac uses register genetics with the repository, and castle windsor has a registration with IRepository<>. For these IoCs it means that you can ctor inject the IRepository with any entity you like. Essentially the factory you wanted. Does Unity not have such a registration possibility?
I think this will do it in unity:
container.RegisterType(typeof(IRepository<>), typeof(Repository <>), new TransientLifetimeManager());