【问题标题】:Simple Injector and assembly scanning简单的喷油器和组件扫描
【发布时间】:2016-08-08 09:46:13
【问题描述】:

我终于开始深入学习 IoC 和其他模式的过程,但在尝试根据程序集列表注册开放泛型时遇到了问题。我将框架的核心构建到单独的类库中,并有一组测试项目,我在其中声明了一些从我的框架继承的测试类。

问题是 AddPersonCommandHandler : ICommandHandler<AddPersonCommand> 所在的 framework.test.service dll 在运行时未加载,因此 ICommandHandler<> 开放泛型无法找到任何内容。我需要提前创建一个AddPersonCommandHandler 实例,然后在我的列表中获得一个额外的程序集,然后它就可以工作了。

有没有简单的强制加载方法?

============ 编辑: 所以这是我的单元测试项目中的连线代码,它包含应用程序域和对其他程序集的引用。

public Container SetupIoc()
{
    var container = new Container();

    container.Register(typeof(IUnitOfWork), typeof(EntityFrameworkUnitOfWork), Lifestyle.Singleton);

    var assemblies = AppDomain.CurrentDomain.GetAssemblies();

    container.Register(typeof(ICommandHandler<>), assemblies);


    container.Verify();

    return container;
}

IUnitOfWork 在 Database.Interface.dll 中 ICommandHandler&lt;&gt; 在 Core.dll 中 AddPersonCommandHandler 在 Test.Service.dll 中——作为一套项目设置结构的一部分,模仿将真正的解决方案放在一起并被单元测试引用。

所以,我认为单元或工作注册工作正常,因为我直接指定UnitOfWorkICommandHandler 接口位于成功绑定的核心中。 Post Verify() 我只看到container 上的工作单元注册。要加载 Test.Service.dll 以便出现 AddPersonCommandHandler,我可以在我的 TestInit 方法中实例化 AddPersonCommand

不得不手动加载项目的所有 dll 似乎有点疯狂。如果我扫描执行文件夹中的 dll,有些已经加载了......再次加载会很好地播放还是需要仔细检查以确定它是否已经加载?

【问题讨论】:

  • 根据使用的框架,您可以使用基于文本的配置来显式注册/加载类型,或者您可以使用 Assembly.Load() 手动执行此操作(添加程序集引用不会使其加载到运行)。现在我不确定我是否完全理解这个问题。
  • 我看过其他的决议,所以做了研究。我想知道是否必须自己扫描程序集并加载它们是唯一的方法
  • 能否展示注册代码并告诉我们使用的是哪个平台,mvc、wpf、windows服务等。
  • 这只是 Visual Studio 中的一堆类库和一个单元测试项目,.NET 4.6.1 和 Simple Injector 3.2.0。有关代码,请参阅我原始帖子中的编辑。

标签: c# .net dependency-injection simple-injector


【解决方案1】:

您不必显式创建AddPersonCommandHandler 的实例来确保程序集已加载。您所要做的就是在调用AppDomain.CurrentDomain.GetAssemblies() 之前运行的代码中静态引用程序集中的一个类型(例如您的AddPersonCommandHandler)。例如:

// Load BL assembly
Type type = typeof(AddPersonCommandHandler);

container.Register(typeof(ICommandHandler<>), AppDomain.CurrentDomain.GetAssemblies());

最好将此引用保留在您的合成根中。这可确保无论容器从何处初始化(App_start 或集成测试),加载相同的程序集。

一种更明确的方法是明确列出应该用于注册的程序集:

// Adding the (redundant) namespace of the type makes it very clear to the
// user if this type is still located in the business layer.
Assembly[] businessLayerAssemblies = new[] {
    typeof(MyComp.MyApp.BusinessLayer.AddPersonCommandHandler).Assembly
}

container.Register(typeof(ICommandHandler<>), businessLayerAssemblies);
container.Register(typeof(IQueryHandler<,>), businessLayerAssemblies);
container.Register(typeof(IEventHandler<>), businessLayerAssemblies);
container.Register(typeof(IValidator<>), businessLayerAssemblies);

我更喜欢后一种方法,因为这样可以防止扫描大量从不包含有用类型的程序集,同时对程序集非常明确(而不是隐式引用恰好加载其程序集的类型)。

【讨论】:

  • 酷伙伴。虽然这是工作,但我宁愿不必这样做,我认为这是一种简单的方法。感谢您的宝贵时间。
  • @StephenYork 或者,您也可以使用this
  • 是的,我希望避免这种情况,并喜欢您原始回复中的选项 B。再次感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多