解决插件体系结构中的Ninject版本冲突

时间:2014-06-12 14:22:38

标签: c# plugins ninject

我有一个支持插件的应用程序。这些插件是加载到独立应用程序域中的DLL集。我的主应用程序在这些域中查找类(通过Ninject.Extensions.Conventions)继承自IPlugin,并以下列方式将这些类绑定到具体的插件实现:

var kernel = new StandardKernel();
kernel.Bind(scanner => scanner.From(pluginAssemblies).SelectAllClasses()
      .InheritedFrom<IPlugin>().BindWith<CustomBindingGenerator<IPlugin>>());

//CustomBindingGenerator
public class CustomBindingGenerator<TInterface> : IBindingGenerator
{
    public static readonly string MetadataKey = "PluginKey";

    public IEnumerable<IBindingWhenInNamedWithOrOnSyntax<object>> CreateBindings(Type type, IBindingRoot bindingRoot)
    {
        Type interfaceType = typeof(TInterface);
        if (!interfaceType.IsAssignableFrom(type))
            yield return null;
        yield return (IBindingWhenInNamedWithOrOnSyntax<object>)bindingRoot.Bind(interfaceType).To(type).WithMetadata(MetadataKey, type.FullName);
    }
}

这一切都很好 - 插件已加载,然后可以根据需要旋转并执行。当我尝试向插件本身提供依赖注入功能时,我的问题就出现了,因此插件可以使用构造函数注入来实现其特定的应用程序依赖性。我让每个插件定义了一个IDependencySpecification,它传递了对同一个内核的引用,该内核保存了程序集中所有插件的绑定(即,上面的kernel相同):

public class MyPluginDependencySpecification : IDependencySpecification
{
    public void SetupDependencies(IKernel kernel)
    {
         kernel.Bind<IMyService>().To<MyService>();
         ....
    }
}

这很有效 - 只要主应用程序使用的Ninject版本与插件正在使用的Ninject版本相同。一些较新的插件开始依赖需要更新版本的Ninject的库,并且在尝试加载此IDependencySpecification时,我的主应用程序抛出一个错误,说它没有实现SetupDependencies方法。

总之,即使我试图以几乎所有方式(通过应用程序域等)将我的插件与我的应用程序隔离,但这个Ninject引用正在泄漏(必要时)并且现在开始导致版本冲突错误。 有没有办法可以重构这个架构以避免这个问题,并且仍然允许我的插件指定自己的依赖注入绑定?

1 个答案:

答案 0 :(得分:1)

当插件需要使用与程序正在使用的相同版本的ninject时,但依赖于不同版本的功能,......那就是无法正常工作。

我们可以改变两件事

  • 确保插件始终使用与程序
  • 相同的版本构建
  • 启用插件以使用任何喜欢的容器

通过实现类似于ninject child kernel extension的内容,可以消除对使用相同IoC版本的限制:

应用程序创建并使用主内核。 每个插件都使用它自己的IoC。 Ninject,Unity,Autofac,你的名字。 IoC以某种方式进行扩展,当它本身无法满足请求时,它会将其传递到应用程序的主内核。

您需要提供访问主内核的界面。您还需要特定于容器的“子内核”扩展实现,这些实现可能需要在IoC更新时进行更新。

子内核实现实际上很小,请参阅https://github.com/ninject/ninject.extensions.childkernel/blob/master/src/Ninject.Extensions.ChildKernel/ChildKernel.cs