tom*_*omo 7 architecture asp.net-mvc ninject inversion-of-control
我正在使用asp.net mvc技术设计中型网站.所有业务逻辑都组织成IServices(如IDomainService,IUserService,IAuthService,ITrainingService).所有服务都使用IRepositories.我正在使用Ninject 1.5与控制器连接服务,它似乎工作得很好.
到目前为止,有一个主题我不知道如何处理.一些服务创建上下文(每个请求) - 例如,IDomainService创建IConserService所需的DomainContext(每个请求).ITrainingService仅在TrainingController中使用,只能由授权用户访问,ITrainingService需要UserContext(也可根据请求)知道谁正在接受培训.
这是我的第一个使用IoC容器的项目.是否有任何设计模式或代码架构如何解决?我想我可以使用ActionFilters来填充上下文对象,但是如何管理它们的生命周期以及将它们放在哪里可供IServices访问?(以一种优雅的方式)
Pet*_*yer 10
我在MVC应用程序中专门使用了Ninject.使用Ninject完成此任务的方法是配置或绑定依赖项.执行此操作时,您可以指定希望如何管理对象生存期.在大多数Web应用程序的情况下,您的对象将按照您在问题中指出的每个请求进行.
我在你的问题中注意到的一件事是你的DomainContext是由IDomainService对象创建的,并被其他对象使用.如果域服务对象是DomainContext的一种工厂,那么您没有太多问题 - 这将成为您如何配置Ninject以提供具体对象和注入依赖项的练习.
以下是关于如何构建应用程序的一般指导 - 请记住,我没有完全理解您的接口和类:
public class GlobalApplication : NinjectHttpApplication {
protected override void RegisterRoutes(RouteCollection routes) {
// Your normal route registration goes here ...
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = "" }
);
}
// This function is resposible for creating a Ninject kernel. This is where
// the magic starts to happen.
protected override IKernel CreateKernel() {
var modules = new IModule[] {
new AutoWiringModule(),
new AutoControllerModule(
Assembly.GetExecutingAssembly()),
new ServiceModule()
};
return new StandardKernel(modules);
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,让Ninject工作的最简单方法是从NinjectHttpApplication类派生您的应用程序类.您需要将RegisterRoutes更改为覆盖方法,并且还需要实现名为CreateKernel的方法.该CreateKernel方法负责返回Ninject内核本身是IoC容器.
在CreateKernel方法中,Ninject提供的AutoControllerModule扫描MVC控制器类的程序集并将其注册到容器中.这意味着Ninject现在可以注入对这些控制器的依赖,因为它已成为应用程序的控制器提供者.该ServiceModule类是一个你需要创建Ninject注册所有服务.我猜它看起来像这样:
internal class ServiceModule : StandardModule {
public override void Load() {
Bind<IDomainService>()
.To<MyDomainService>()
.Using<OnePerRequestBehavior>();
Bind<DomainContext>()
.ToMethod( ctx => ctx.Kernel.Get<IDomainService>().CurrentDomainContext )
.Using<OnePerRequestBehavior>();
Bind<IService>()
.To<MyServiceType>()
.Using<OnePerRequestBehavior>();
}
}
Run Code Online (Sandbox Code Playgroud)
Ninject有一个非常富有表现力的流畅的配置界面.请注意,每个语句基本上将具体类与其实现的接口相关联.语句中的"Using"短语向Ninject内核指示该对象仅在请求的生命周期内存在.因此,例如,这意味着无论何时在同一请求期间从Ninject内核请求IDomainService对象,都将返回相同的对象.
至于你的上下文对象,我正在尝试你的域服务创建这些上下文并充当各种工厂.在这方面,我通过从IDomainService获取名为CurrentDomainContext的属性的值来生成上面的DomainContext类.这就是上面的lambda完成的.Ninject中"ToMethod"绑定的好处在于您可以访问Ninject激活上下文对象,该对象允许您使用内核解析对象.这正是我们为了获得当前域上下文所做的.
接下来的步骤是确保您的对象正确接受依赖项.例如,您说ITrainingService仅用于TrainingController类.因此,在这种情况下,我将确保TrainingController具有接受ITrainingService参数的构造函数.在该构造函数中,您可以在成员变量中保存对ITrainingService的引用.如:
public class TrainingController : Controller {
private readonly ITrainingService trainingService;
public TrainingController(ITrainingService trainingService) {
this.trainingService = trainingService;
}
// ... rest of controller implementation ...
}
Run Code Online (Sandbox Code Playgroud)
请记住,Ninject已经使用Ninject内核注册了所有控制器,因此在创建此控制器并调用其操作时,您将通过trainingService成员变量引用ITrainingService.
希望这可以帮助你.使用IoC容器有时会变得非常混乱.注意,我强烈建议您查看Ninject文档 - 它是对Ninject以及DI/IoC概念的精心编写的介绍.我也没有讨论过上面显示的AutoWiringModule; 然而,内特Kohari(Ninject的创建者)具有良好的写了在他的博客有关此功能.
祝好运!
| 归档时间: |
|
| 查看次数: |
1061 次 |
| 最近记录: |