我的应用程序包括许多后端程序集(包括实体框架数据存储库层),它们由许多前端程序集(包括 Windows 服务和 MVC3 Web 应用程序)共享。
我对 Ninject 绑定过程的理解是,每个包含可注入类型的程序集还应该包含一个定义这些类型的默认绑定的 Ninject 模块。然后,定义的模块集将被加载到使用程序集的 Ninject 内核中。
但是,我遇到了问题,因为所需的绑定范围并不总是一致的。例如,我的MVC项目需要绑定到数据上下文InRequestScope
,而 Windows 服务绑定到同一个类InThreadScope
.
显然,我可以通过将所有模块重新定位到前端项目中来解决这个问题,从而为每个使用场景维护每个模块的单独副本,但这似乎很麻烦,因为它在多个项目中复制了大部分模块内容。
是否有关于模块应位于多层应用程序中的位置的最佳实践,以及如何将其与绑定项目之间差异的需求相协调?
非常感谢您的建议,
Tim
对于单个应用程序的解决方案,一般建议是在应用程序项目(您的 Web 应用程序或 Web 服务项目)中注册您的容器。对于 Web 应用程序,这通常是 Global.asaxApplication_Start
。将所有东西连接在一起的地方称为成分根在 DI 术语中。
使用多应用程序解决方案,每个应用程序项目仍然有一个组合根。这是必须的,因为每个应用程序都有其独特的配置。另一方面,重复的代码总是不好的。当您引入新的抽象时,您不希望必须更改三个地方。
诀窍是将所有注册在项目层次结构中向下移动。例如,您可以定义一个依赖于业务层程序集(及以下)的“引导程序集”,并让它拥有那些不更改的程序集的所有注册。然后,应用程序的组合根可以使用该程序集来获取默认注册,并使用应用程序特定的依赖项对其进行扩展。
这样的事情可能看起来像这样:
// MVC Composition root
public static void Bootstrap()
{
var container = new Container();
// Default registrations
BusinessLayerBootstrapper.Bootstrap(container);
// Application specific registrations
container.Bind<IUserContext>().To<AspNetUserContext>();
DependencyResolver.Current =
new ContainerDependencyResolver(container);
}
// Windows Service Composition root
public static void Bootstrap()
{
var container = new Container();
// Default registrations
BusinessLayerBootstrapper.Bootstrap(container);
// Application specific registrations
container.Bind<IUserContext>().To<SystemUserContext>()
.SingleScoped();
// Store somewhere.
Bootstrapper.Container = container;
}
// In the BL bootstrap assembly
public static class BusinessLayerBootstrapper
{
public static void Bootstrap(Container container)
{
container.Bind<IDepenency>().To<RealThing>();
// etc
}
}
尽管您不需要单独的引导程序程序集(您可以将此代码放置在 BL 本身中),但这使您可以使业务层程序集免受容器的任何依赖。
另请注意,我只是调用静态Bootstrap()
方法,而不是使用 (Ninject) 模块。我试图让我的答案独立于框架,因为你的问题很笼统,并且对于所有 DI 框架的建议都是相同的。不过,如果您愿意,当然可以使用 Ninject 模块功能。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)