单例,静态方法和Web服务可伸缩性

时间:2014-08-12 18:36:55

标签: asp.net web-services singleton scalability static-methods

我有一个使用asp net和mvc4 api运行的web服务。

对于每个请求,我都有一个控制器,例如: GetUserData,GetStates等

这些控制器中的每一个都访问一个Manager类(它是一个单例)来从中检索数据。 Manager类中的所有方法都是无上下文且独立的。

public class StatesController : ApiController
{
    public List<StateModel> Get()
    {            
        return Manager.Instance.GetStates();
    }
}

有人告诉我,这对Web应用程序的可伸缩性不利。我该怎样绕过这个? 我应该在Manager类中使这些方法静态吗?我应该将整个方法移动到控制器类吗?是否应该每次都使构造函数公开并实例化Manager类(Manager类几乎没有属性和字段,只有一堆方法)?有一些更好的方法吗?

谢谢!

1 个答案:

答案 0 :(得分:0)

我将在很高的层次上解释这一点,但一种方法是将你的GetStates()逻辑重新定位到它自己的类 - 即StateRepository或类似的东西。也许您围绕这个“存储库”概念构建了几个接口:

public interface IRepository<TEntity> where TEntity : class
{
    IEnumerable<TEntity> All();
}

public interface IStateRepository : IRepository<State>
{
    IEnumerable<State> All();
}

现在实现您的存储库:

public class StateRepository : IStateRepository
{
    public IEnumerable<State> All()
    {
        // retrieve states from file/DB/service etc.
    }
}

现在我们继续讨论下一个概念:依赖注入(DI)。不知何故,您需要让控制器成为StateRepository的实例,但我们希望保持低耦合。 DI让你可以很好地完成这项工作。设置完成后,您的控制器如下所示:

public class StatesController : ApiController
{
    private readonly IStateRepository _stateRepository;

    public StatesController(IStateRepository stateRepository)
    {
        _stateRepository = stateRepository;
    }

    public List<StateModel> Get()
    {            
        return _stateRepository.All();
    }
}

将DI注入你的WebApi有很少的工作,但是一旦完成,你将只有一行代码,例如(例如[Ninject syntax]):

Bind<IStateRepository>().To<StateRepository>().InRequestScope();
                                       // or  .InSingletonScope();

现在,只要调用控制器,StateRepository的新(请求范围)或现有(单例范围)实例就会自动传递(“注入”)到其构造函数。

通常认为这种方法更具可扩展性。想要模拟一些单元测试数据?创建一个实现MockedStateRepository的{​​{1}}并更改绑定。想要在整个应用中使用IStateRepository吗?简单。未来的维护更容易。这个清单一直在继续,但也许你应该自己做研究。