我有一个使用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类几乎没有属性和字段,只有一堆方法)?有一些更好的方法吗?
谢谢!
答案 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
吗?简单。未来的维护更容易。这个清单一直在继续,但也许你应该自己做研究。