【问题标题】:How to use Ninject Conventions extension without referencing Assembly (or Types within it)如何在不引用程序集(或其中的类型)的情况下使用 Ninject Conventions 扩展
【发布时间】:2010-10-25 23:06:49
【问题描述】:

很抱歉这个问题太长了,因为我整天都在研究这个问题。

一般问题:

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

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

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

Bind<ISomeService>.To<SomeService>;

因此,了解了 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;
    }

我想要完成的事情:

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

由于我们的 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 文件 (x86)\通用文件\微软 Shared\DevServer\10.0\MyApp.Data' 或其依赖项之一。系统 找不到文件 指定。":"file:///C:\Program Files (x86)\通用文件\微软 共享\DevServer\10.0\

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

我查看了 Ninject.Extensions.Conventions 的源代码,我承认我完全不知道它应该如何工作,但我可以看到它在做什么。

程序集扫描器会在我们调用各种 FromXXX 方法时建立要扫描的程序集列表。

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

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

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

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

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

呃..又是什么问题:

谁能解释如何让 Ninject 约定按名称加载程序集,而不创建对程序集的引用并通过指定包含类型来加载它?请。

我已经搜索了Ninject google group 的页面和页面,并且我已经阅读了它的only (so it seems) relevant documentation 并且还没有能够解决它......但是。

【问题讨论】:

  • 你在这个问题上做得很好。现在我会在邮件列表上交叉发布这个 - 那里有更多人使用不太主流的场景,他们并不都看这里......

标签: c# .net dependency-injection inversion-of-control ninject


【解决方案1】:

此问题已在邮件列表中得到解答。 http://groups.google.com/group/ninject/browse_thread/thread/a7f2163e060a6d64

简而言之:

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

【讨论】:

  • 添加了对完全限定文件名的支持:只要程序集位于探测路径中,a.From("AnotherDependency, Version=1.0.0.0, PublicKeyToken=null") 现在应该可以工作。
【解决方案2】:

我不确定这是否是您的示例中的拼写错误,但我确实注意到您已经写了

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

但不应该这样

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

因为如果我在示例项目中包含 .dll 部分,它可以正常工作,但如果我不使用它,我会收到 FileNotFoundException。

【讨论】:

  • 这不是错字。我放了几个不同的表格来说明我尝试过的各种事情。我确实尝试过使用和不使用“.dll”并收到相同的错误。
猜你喜欢
  • 2018-05-10
  • 1970-01-01
  • 1970-01-01
  • 2015-07-02
  • 1970-01-01
  • 2019-05-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多