编程语言
首页 > 编程语言> > c# – web api控制器和城堡windsor生活方式

c# – web api控制器和城堡windsor生活方式

作者:互联网

在web api控制器功能中,我使用两种服务,因为它们做独立的东西,我希望它们使用不同的工作单元(事务).

所有必要的组件(工作单元,存储库)都通过带有LifestylePerWebRequest的城堡windsor注入.

据我所知,解决方案是使用LifeStyleScoped但我有两个问题:

>我希望LifeStyleScoped仅适用于这种特殊情况而不是一般情况
>我找不到如何在控制器中使用LifeStyleScoped的单个示例.

任何其他建议或代码示例将不胜感激.

编辑:我没有提到单元工作没有在控制器中明确注入.在控制器中注入两个服务,这些服务使用通过城堡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) {

    }
}

解决方法:

如果您在Web API应用程序中使用Castle.Windsor,您可能已经在使用IDependencyResolver,您可以将其连接起来使用Windsor自己的范围,类似于:

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将为每个请求创建一个新范围,并在请求完成后进行处理.因此,如果您使用这种技术,您可以取消LifestylePerWebRequest并简单地使用LifestyleScoped,从而解决了为每个组件进行两次注册的需要.

第二个挑战是:你如何获得第二个独立的工作单位?显然,所有强制和可选的控制器依赖关系都将在同一ILifetimeScope中隐式解析,因此简单地天真地声明第二个IUnitOfWork的构造函数依赖关系将不起作用.

有很多方法可以做到这一点,但是如果你准备好使用Service Locator Anti-Pattern,你可以简单地创建自己的范围,如下所示:

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...
    }
}

标签:c,asp-net-web-api,castle-windsor
来源: https://codeday.me/bug/20190623/1274019.html