Blu*_*ird 1 nhibernate dependency-injection asp.net-mvc-3
请在以下情况下纠正我.(问题在最后)
(我问了一个类似的问题,这个问题是没有组织的,并且被投票结束.所以我把这里的问题概括为一个范围,可以回答确切的答案.)
我正在开发一个使用nhibernate作为ORM的多层Web应用程序.我的图层结构如下
使用上面的层,类和接口如下放置.
ProductController.cs(UI层)
public class ProductController : Controller
{
ProductServices _ProductServices;
NHibernate.ISession _Session;
public ProductController()
{
_Session = SessionManager.GetCurrentSession();
_ProductServices = new ProductServices(
new ProductRepository(), _Session);
}
// Cont..
}
Run Code Online (Sandbox Code Playgroud)
ProductServices.cs(服务层)
public class ProductServices : IProductServices
{
protected IProductRepository _ProductRepository;
protected NHibernate.ISession _Session;
public ProductServices(IProductRepository productRepository,
NHibernate.ISession session)
{
_ProductRepository = productRepository;
_Session = session;
_ProductRepository.SetSession(_Session);
}
// cont...
}
Run Code Online (Sandbox Code Playgroud)
ProductRepository.cs(存储库层)
public class ProductRepository : IProductRepository
{
NHibernate.ISession _Session;
public void SetSession(NHibernate.ISession session)
{
_Session = session;
}
public IEnumerable<Product> FindAll()
{
return _Session.CreateCriteria<Product>().List<Product>();
}
//cont..
}
Run Code Online (Sandbox Code Playgroud)
在UI层,我按会话请求创建会话,并在类构造函数的帮助下注入服务层.然后在方法的帮助下设置存储库的会话.
我担心如果我将_Session作为构造函数直接传递给存储库,我将无法在服务层下控制它.此外,还有一个使用Web服务层的未来扩展计划.
**有没有办法确保_Session已经设置的ProductRepository类的每个方法,而不是在每个方法中编写代码片段,if(_Session==null)因为它重复相同的代码.
**如果上述模式错误,请告诉我实现此目标的正确方法.
你在做什么让我感到惊讶.你应用构造函数注入模式ProductService,这绝对是你要走的路.另一方面,您没有将依赖项注入到ProductController该类中,但该类通过静态类(这是Service Locator反模式)请求其中一个依赖项,并ProductServices自己创建一个类.这使得这个类难以测试并使您的应用程序不那么灵活和可维护,因为ProductServices当它在多个地方使用时,您无法轻易地更改,装饰或拦截类的使用.
虽然您(正确地)使用构造函数注入来处理依赖项,但是ProductServices您将这些依赖项传递给产品存储库,而不是同时应用构造函数注入模式ProductResopistory.
请告诉我实现这一目标的正确方法.
正确的方法是在任何地方应用构造函数注入模式.执行此操作时,您的代码将开始如下所示:
public class ProductController : Controller
{
private ProductServices _ProductServices;
public ProductController(ProductServices services)
{
_ProductServices = services;
}
// Cont..
}
public class ProductServices : IProductServices
{
private IProductRepository _ProductRepository;
public ProductServices(
IProductRepository productRepository)
{
_ProductRepository = productRepository;
}
// cont...
}
public class ProductRepository : IProductRepository
{
private ISession _Session;
public ProductRepository (ISession session)
{
_Session = session;
}
public IEnumerable<Product> FindAll()
{
return _Session
.CreateCriteria<Product>().List<Product>();
}
//cont..
}
Run Code Online (Sandbox Code Playgroud)
了解每个类如何仅使用它自己使用的依赖项.所以,ProductController并且ProductServices不依赖于ISession(我做出了只ProductRepoistory需要的假设ISession).从课堂的角度来看 - 现在一切都变得简单了吗?
我们真的在这里解决了问题吗?看起来我们刚刚将所有类连接起来的问题转移到依赖图上.是的,我们确实解决了这个问题 这是一件好事.现在,每个类都可以单独测试,更容易遵循,整个应用程序更易于维护.
但是,在应用程序的某处,ProductController必须创建一个.这看起来像这样:
new ProductController(
new ProductServices(
new ProductRepository(
SessionManager.GetCurrentSession())));
Run Code Online (Sandbox Code Playgroud)
在其正常配置中,ASP.NET MVC将为您创建控制器类,并且它需要一个默认构造函数来执行此操作.如果你想使用构造函数注入(你肯定应该这样做)连接控制器,你需要做一些"特殊"的事情才能使它工作.
ASP.NET MVC允许您覆盖默认ControllerFactory类.这允许您决定如何创建控制器实例.但是,当您的应用程序开始增长时,当您手动创建依赖关系图时,它会很快变得非常尴尬(正如我的上一个示例所示).在这种情况下,使用依赖注入框架会好得多.其中大多数都包含一个功能/包,允许您将其与ASP.NET MVC集成,并自动允许在MVC控制器上使用构造函数注入.
我们完成了吗?嗯...我们曾经吗?你的设计中有一件事在我脑中引发了一面旗帜.您的系统包含一个名为的类ProductServices.虽然这是一个疯狂的猜测,但这个名称Services似乎包含了该类中所有与产品相关的业务操作.根据系统的大小,团队中的人数以及需要进行的更改量,这可能会出现问题.例如,如何以系统保持可维护的方式有效地应用横切关注点(例如日志记录,验证,分析,事务管理,容错改进)?
因此,不是将所有操作包装在单个ProductServices类中,而是尝试为每个业务事务/用例提供自己的类,并将相同(通用)接口应用于所有这些类.这种描述可能有点模糊,但它是提高小型和大型系统可维护性的好方法.你可以在这里阅读更多相关信息.
| 归档时间: |
|
| 查看次数: |
1193 次 |
| 最近记录: |