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

que*_*rin 18 .net c# dependency-injection ninject inversion-of-control

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

一般问题:

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

我们编写接口代码并将Ninject 2用于DI/IoC.

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

Bind<ISomeService>.To<SomeService>;
Run Code Online (Sandbox Code Playgroud)

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

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

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

    public static IKernel Initialize()
    {
        var kernel = new StandardKernel();

        kernel.Scan(a => {
                        a.FromAssemblyContaining<MyApp.Data.SomeDataClass>();
                        a.FromAssemblyContaining<MyApp.Services.SomeServiceClass>();
                        a.AutoLoadModules();
                        a.BindWithDefaultConventions();
                        a.InTransientScope();
                    });

        return kernel;
    }
Run Code Online (Sandbox Code Playgroud)

我想要完成的事情:

但是......我想以一种我认为支持的方式进一步采取这一点,但我似乎无法让它发挥作用.

由于我们的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;
    }
Run Code Online (Sandbox Code Playgroud)

但我收到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中.这是因上述异常而失败的步骤.

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

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

呃......又是什么问题:

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

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

Rem*_*oor 4

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

简而言之:

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