如何在不引用程序集(或其中的类型)的情况下使用Ninject Conventions扩展

对于这个长期的问题,提前抱歉,这很长,因为我整天都在挖掘这个问题。

一般问题:

我有一个ASP.Net MVC2应用程序,其中包含以下项目:MyApp.Web,MyApp.Services,MyApp.Data。

我们对接口进行编码并将Ninject 2用于DI / IoC。

但是,我对打字(并忘记输入)感到非常厌倦:

Bind.To; 

所以,了解Ninject.Extensions.Convensions,我试图用它来自动扫描和注册模块和IXxxx => Xxxx类型的简单依赖项。

我试过的是有效的(但还不够):

我可以使用以下代码来设置Ninject,并且所有内容似乎都按预期连接。

  public static IKernel Initialize() { var kernel = new StandardKernel(); kernel.Scan(a => { a.FromAssemblyContaining(); a.FromAssemblyContaining(); a.AutoLoadModules(); a.BindWithDefaultConventions(); a.InTransientScope(); }); return kernel; } 

我想要完成的事情:

但是……我想以一种我认为支持的方式更进一步,但我似乎无法让它发挥作用。

由于我们的MyApp.Web项目根本没有使用MyApp.Data(直接),我试图避免引用MyApp.Data。 使用上面的代码,我必须从MyApp.Web引用MyApp.Data,因为对SomeDataClass的编译时引用。

我更愿意为Ninject指定一个程序集的名称进行扫描和注册。 看来,Conventions扩展通过From过载来支持这个,它带有一个字符串(或可枚举的字符串)。

我尝试了什么以及它如何打破:

所以,我在From重载上尝试了几种变体:

  public static IKernel Initialize() { var kernel = new StandardKernel(); kernel.Scan(a => { a.From("MyApp.Data"); a.From("MyApp.Services.dll"); a.From("AnotherDependency, Version=1.0.0.0, PublicKeyToken=null"); //etc., etc. with the From(...)'s a.AutoLoadModules(); a.BindWithDefaultConventions(); a.InTransientScope(); }); return kernel; } 

但我收到FileNotFoundExceptions,消息如下:

无法加载文件或程序集’file:/// C:\ Program Files(x86)\ Common Files \ Microsoft Shared \ DevServer \ 10.0 \ MyApp.Data’或其依赖项之一。 系统找不到指定的文件。“:”file:/// C:\ Program Files(x86)\ Common Files \ Microsoft Shared \ DevServer \ 10.0 \

我发现自己试图解决这个问题:

我已经检查了Ninject.Extensions.Conventions的来源,我承认我完全迷失了它应该如何工作,但我可以看到它在做什么。

当我们调用各种FromXXX方法时,汇编扫描器会构建要扫描的程序集列表。

当我调用From(“assemblyName”)方法时,它首先检查列表是否已包含其中assembly.AssemblyName.Name等于我传入的名称的任何程序集(而AssemblyName.Name是简单名称,即MyApp.Data,根据MSDN)。

Flow通过一些不重要的方法,登陆FindAssemblies方法。 这个方法采用我传入的名称(我们已经看到它应该是一个简单的程序集名称)。 然后它创建一个新的AssemblyName,我们的传入名称用作AssemblyName.CodeBase。

然后,它尝试将程序集加载到临时AppDomain中。 这是因上述exception而失败的步骤。

显然,它搜索的路径是错误的,但是我无法通过From()方法提供路径。 这也行不通。

我已经尝试了其他一些FromXXX方法,但我已经无处可去,并且已经花了太多时间在这上面。 FromAssembliesInPath和FromAssembliesMatching也不起作用,因为它再次搜索完全错误的目录。

呃……又是什么问题:

任何人都可以解释如何让Ninject Conventions按名称加载程序集,而不创建对程序集的引用并通过指定包含类型加载它? 请。

我已经搜索了Ninject谷歌小组的页面和页面,我已经阅读了它( 仅仅是相关的)相关文档并且还无法解决它。

这个问题已在邮件列表中回答。 http://groups.google.com/group/ninject/browse_thread/thread/a7f2163e060a6d64

简而言之:

  1. 表单(路径)从工作目录或绝对路径获取相对路径
  2. 程序集必须驻留在探测路径中,因为它被加载到加载上下文中以避免切换加载上下文时的其他问题。
  3. 开发服务器使所有程序集复制到它们自己的目录中变得复杂,这使得无法使用调用程序集来创建路径。 这意味着使用开发服务器的Web应用程序的唯一方法。
  4. 我们将在未来版本中添加对程序集的完全限定名称的支持,以使其更容易。

我不确定这是你的例子中的拼写错误,但我确实注意到你写过了

 kernel.Scan(a => { a.From("MyApp.Data"); // etc. } 

但不应该这样

 kernel.Scan(a => { a.From("MyApp.Data.dll") // etc. }); 

因为如果我在我的示例项目中包含.dll部分它可以工作,但是如果我把它留下来,我会收到一个FileNotFoundException。