3

我的应用程序实现了一种模块化架构,可以动态加载一个或多个“插件”程序集。每个程序集都包含一个实现IPlugin接口的类,提供宿主应用程序用来与插件交互的各种方法和属性。

这个类不可避免地依赖于插件中的其他类,而这些类又可能有自己的依赖关系。到目前为止,我一直在使用 Castle Windsor 管理所有这些(每个插件都包含一个IWindsorInstaller我注册其依赖项的位置),并通过它们的构造函数进行 DI。缺点是类必须是public这种方法才能工作。

我现在已经意识到并想通过制作所有这些类来锁定插件internal,但是我不确定处理依赖项的最佳方法,因为大概我将无法使用 Windsor。我不希望这些类实例化它们自己的依赖项(不是松散耦合、缺乏可测试性等),那么还有哪些其他方法呢?

4

2 回答 2

3

缺点是这些类必须是公开的才能使这种方法起作用。

这不是真的。您可以注册内部的东西,但您可能会失去 Castle Windsor(或任何 DI 容器)的自动连接(自动构造函数注入)功能。您可以通过注册手动创建这些类型的委托来注册内部内容。例如:

container.Register(Component.For<IService>()
    .UsingFactoryMethod(() =>
    {
        var log = container.Resolve<ILogger>();
        return new RealService(log);
    })
    .LifeStyle.Transient);

手动创建服务new不是最理想的,因为自动连接使插件程序集的组合根保持最大的可维护性,但我认为在你的情况下没有一个好的选择。不过,这比让每个服务创建自己的依赖项(穷人的 DI)要好。

更新

我记得一件事:当您使用泛型方法注册这些内部类型时,应该仍然可以使用内部类型进行自动装配,例如这个:

container.Register(Component.For<IService>()
    .ImplementedBy<RealService());

为此,构造函数RealService必须是公共的(但RealService它本身可以是内部的)。这甚至可以在部分信任的情况下工作,例如在非常严格的 Silverlight 沙箱中运行时(或者至少,它可以与 Simple Injector 一起使用,但 Castle 也应该能够做到这一点)。

于 2012-10-12T21:57:24.847 回答
0

如果您使用 Ninject,您可以将NinjectModule添加到每个配置绑定的程序集,然后在主机应用程序中简单地加载模块以注册绑定。

public class ServiceModule : NinjectModule
{
    public override void Load() 
    {
        Bind<IService>().To<RealService>();
    }
}

可以留在RealService内部,模块可以看到它,因为它在同一个组件内。

于 2012-10-12T22:38:57.533 回答