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

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

提前抱歉这个长问题,它很长是因为我整天都在挖掘这个问题。

一般问题:

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

我们对接口(interface)进行编码并将 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。对于上面的代码,由于编译时对 SomeDataClass 的引用,我必须从 MyApp.Web 引用 MyApp.Data。

我更愿意指定程序集的名称 以便 Ninject 扫描和注册。约定扩展似乎通过采用字符串(或可枚举的字符串)的 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,其中包含如下消息:

Could not load file or assembly 'file:///C:\Program Files (x86)\Common Files\Microsoft Shared\DevServer\10.0\MyApp.Data' or one of its dependencies. The system cannot find the file specified.":"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 约定按名称加载程序集,而不创建对程序集的引用并通过指定包含的类型加载它?请。

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

最佳答案

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

简而言之:

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

关于c# - 如何在不引用程序集(或其中的类型)的情况下使用 Ninject 约定扩展,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4019585/

相关文章:

c# - 这是众所周知的设计模式吗?它叫什么名字?

c# - 在 3 个实体之间创建导航属性

c# - Log4Net:处置 MemoryAppender

c# - 检查对象是否是委托(delegate)

c# - 在未安装 MS Office 的计算机上使用 Office.Interop.Excel

c# - ADO .NET EF 中的可组合查询每次迭代返回更多实体

c# - 我如何使用 ffmpeg 捕获整个桌面但没有 ffmpeg 的控制台窗口?

xaml - XAML (WPF) 中的依赖注入(inject)

asp.net-mvc - 针对各种应用程序的 Autofac 模块扫描

android - 如何在kodein中使用带有两个参数的工厂绑定(bind)来恢复对象?