Ninject 3.0.0 中的基于约定的依赖注入

9

我的解决方案中有两个项目... 一个是域项目,另一个是MVC3 Web项目(例如MyApp.Domain和MyApp.Web)。以前,当使用Ninject.Extensions.Conventions ver.2时,我能够在NinjectMVC3.cs文件中使用以下语句,并且整个解决方案中所需的依赖项(包括Web和域)都能被正确注入(例如IFoo自动绑定到Foo)。

kernel.Scan(x =>
{
  x.FromAssembliesMatching("*");
  x.BindWith<DefaultBindingGenerator>();
});

我刚刚升级到了Ninject 3.0.0(预发布版)和Ninject.Extensions.Conventions 3.0.0(另一个预发布版),但是基于约定的绑定语法已经改变。我已经弄清楚我可以使用以下语句来适应新版本,但它只会自动绑定MyApp.Web中基于约定的接口,而不是MyApp.Domain中的。以前的版本会在整个应用程序中绑定接口。

kernel.Bind(x => x
    .FromThisAssembly()
    .SelectAllClasses()
    .BindToAllInterfaces());

你知道如何在新版本的Ninject中配置基于约定的绑定吗?我猜这与指定程序集有关,但是我已经尝试使用FromAssembliesMatching("*"),但它会导致所有内容都失败。

-- 编辑以展示我的现有RegisterServices方法中的代码:--

private static void RegisterServices(IKernel kernel)
{
  // This code used to work with v.2 of Ninject.Extensions.Conventions
  // kernel.Scan(x =>
  // {
  //   x.FromAssembliesMatching("*");
  //   x.BindWith<DefaultBindingGenerator>();
  // });

  // This is the new v3 code that automatically injects dependencies but only for interfaces in MyApp.Web, not MyApp.Domain
  kernel.Bind(x => x.FromThisAssembly().SelectAllClasses().BindToAllInterfaces()); 

  // I tried this code, but it throws "Error activating IDependencyResolver" at "bootstrapper.Initialize(CreateKernel)"
  // kernel.Bind(x => x.FromAssembliesInPath(AppDomain.CurrentDomain.RelativeSearchPath).SelectAllClasses().BindToAllInterfaces());

  // These are dependencies in MyApp.Web that ARE being bound properly by the current configuration
  // kernel.Bind<IMemberQueries>().To<MemberQueries>();
  // kernel.Bind<IGrantApplicationQueries>().To<GrantApplicationQueries>();
  // kernel.Bind<IMailController>().To<MailController>();

  // These are dependencies in MyApp.Domain that ARE NOT being bound properly by the current configuration, so I have to declare them manually 
  // They used to be injected automatically with version 2 of the conventions extention
  kernel.Bind(typeof(IRepository<>)).To(typeof(Repository<>)).InRequestScope();
  kernel.Bind<IUnitOfWork>().To<UnitOfWork>().InRequestScope();
  kernel.Bind<IMemberServices>().To<MemberServices>();
  kernel.Bind<IGrantApplicationServices>().To<GrantApplicationServices>();

  // These are dependencies that SHOULD NOT be bound by convention as they require a different scope or have unique naming
  kernel.Bind(typeof(EfDbContext)).ToSelf().InRequestScope();
  kernel.Bind<IConfigurationProvider>().To<WebConfigConfigurationProvider>().InSingletonScope();
  kernel.Bind<IAuthorizationProvider>().To<MyAppAuthorizationProvider>();
  kernel.Bind<IPrincipal>().ToMethod(ctx => HttpContext.Current.User).InRequestScope();
  kernel.Bind<IGrantApplicationDocumentServices>().To<MySpecialNameGrantAplicationDocumentServices>().InRequestScope();
}

你看过维基了吗?如果没有,你能说一下哪个部分让你感到困惑吗? - Ruben Bartelink
Ruben,我看了维基。不明白的是,旧代码中的 x.FromAssembliesMatching("*") 可以工作并绑定 MyApp.Web 和 MyApp.Domain 中的所有接口。然而,在新的 3.0.0 版本中,这个语法不起作用。我找到的最接近的是 x.FromThisAssembly(),但它只会绑定 MyApp.Web 中的接口(因为注入发生在那里)。它不会自动绑定 MyApp.Domain 中的接口。 - bigmac
看代码,你总是可以自己获取程序集(通过AppDomain的程序集列表或其他机制),并显式地提供列表。除此之外,我建议只是阅读源代码 - 它并不大。https://github.com/ninject/ninject.extensions.conventions/blob/master/src/Ninject.Extensions.Conventions/BindingBuilder/AssemblyFinder.cs - Ruben Bartelink
看算法的话,它使用了AppDomain相对搜索路径和基本路径的组合。为了快速排除任何问题,您可以执行.FromAssembliesInPath(AppDomain.CurrentDomain.RelativeSearchPath),它将产生<绝对路径到你的wwwroot\app\bin> - Ruben Bartelink
感谢你的帮助,Ruben。不幸的是,我尝试了那个方法,但现在我收到一个异常,指出“激活IDependencyResolver错误,有多个匹配绑定可用。激活路径:1)请求IDependencyResolver。建议:1)确保您只定义了一次IDependencyResolver的绑定。”我希望新版本能像第二版一样正常工作。 - bigmac
显示剩余2条评论
1个回答

17

等效的代码如下:

kernel.Bind(x => x
    .FromAssembliesMatching("*")
    .SelectAllClasses()
    .BindDefaultInterface());

1
谢谢Remo。我想我是个白痴。那是我尝试的第一件事之一,但我使用了BindToDefaultInterfaces(复数)方法失败了。当我改用单数方法时,它就起作用了。对于所有的帖子,我很抱歉,但我非常感激你的帮助。在你的所有项目上都做得很好! - bigmac

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接