Reputation: 482
Inside a web api controller function i use two services and since they do independent stuff i want them to use different units of work (transactions).
All the necessary components (unit of work, repositories) are injected through castle windsor with LifestylePerWebRequest.
From what i understand a solution is to use LifeStyleScoped but i have two problems:
Any other suggestions or code examples would be appreciated.
Edit: I didn't mention that the unitofwork is not injected explicitly in the controller. Two services are injected in the controller and these services use the unit of work that is created through castle windsor.
public class SomeController : ApiController
{
private readonly IService _service1;
private readonly IService _service2;
public SomeController (IService service1, IService service2)
{
_service1= service1;
_service2= service2;
}
public IHttpActionResult SomeAction()
{
_service1.DoSomething();
_service2.DoSomething();
}
}
public Service : IService
{
public Service(IUnitOfWork uow) {
}
}
Upvotes: 4
Views: 1073
Reputation: 7264
If you are using Castle.Windsor in a Web API app, you are probably already using IDependencyResolver, which you can wire up to use Windsor's own scope, similar to this:
class WindsorDependencyResolver : IDependencyResolver
{
private readonly IWindsorContainer _container;
public WindsorDependencyResolver(IWindsorContainer container)
{
_container = container;
}
public object GetService(Type t)
{
return _container.Kernel.HasComponent(t) ? _container.Resolve(t) : null;
}
public IEnumerable<object> GetServices(Type t)
{
return _container.ResolveAll(t).Cast<object>().ToArray();
}
public IDependencyScope BeginScope()
{
return new WindsorDependencyScope(_container);
}
public void Dispose()
{
}
}
class WindsorDependencyScope : IDependencyScope
{
private readonly IWindsorContainer _container;
private readonly IDisposable _scope;
public WindsorDependencyScope(IWindsorContainer container)
{
_container = container;
_scope = container.BeginScope();
}
public object GetService(Type t)
{
return _container.Kernel.HasComponent(t) ? _container.Resolve(t) : null;
}
public IEnumerable<object> GetServices(Type t)
{
return _container.ResolveAll(t).Cast<object>().ToArray();
}
public void Dispose()
{
_scope.Dispose();
}
}
Web API will create a new scope for each request and dispose it after the request is finished. So if you are using this technique you can probably do away with your LifestylePerWebRequest and simply go with LifestyleScoped, thus resolving the need to have two registrations for each component.
The second challenge then is: how do you get a second independent unit of work? Clearly all of the mandatory and optional controller dependencies will implicitly be resolved within the same ILifetimeScope, so simply naively declaring a constructor dependency for a second IUnitOfWork will not work.
There are a number of ways you could do this, but if you're prepared to live with the Service Locator Anti-Pattern you could simply create your own scope like so:
public class SomeController : ApiController
{
private readonly IUnitOfWork _uow;
public SomeController (IUnitOfWork uow)
{
_uow = uow;
}
public IHttpActionResult SomeAction()
{
// Get a second UoW
using (var separatelyScopedResolver = GlobalConfiguration.Configuration.DependencyResolver.BeginScope())
{
var anotherUoW = separatelyScopedResolver.GetService(typeof (IUnitOfWork));
// Do something with this UoW...
anotherUoW.Save();
}
// Do something with the default UoW...
_uow.Save();
// Et cetera...
}
}
Upvotes: 4