创建整体 IoC 容器

Create overall IoC container

我在项目中使用 IoC 容器,但我的项目包含许多子模块。我想使用一个基本的 IoC 模块。 例子: 我在子模块 A 中有两个接口 是 IOne 和 ITwo 接口

public interface ITwo
{
     // some code
}

public interface IOne
{
     // some code
}

还有我的 SimpleInjectorRegisterTypes class

public class SimpleInjectorRegisterTypes : ISimpleInjectorRegistration
    {
        public void Register(Container container)
        {
            container.RegisterSingle<ITwo, Two>();
            container.RegisterSingle<IOne, One>();
        }
    }

和主要 class,我在其中使用我的逻辑

private static IOne _one;
        private static ITwo _two;

        static void Main(string[] args)
        {
            Container container = new Container();
            new SimpleInjectorRegisterTypes().Register(container);
            _one= container.GetInstance<IOne>();
            _two= container.GetInstance<ITwo>();
        }

很好,但是我有子模块 B,其中我有接口 IThree 和 TFour 还有 SimpleInjectorRegisterTypes 和 main class。 如何为我所有的子模块编写一个通用的 IoC 容器? P.S。对于 IoC,我使用 bootstrapper

假设有 3 个子程序集 CommonModuleAModuleB

  • CommonICommon 界面和你的 ISimpleInjectorRegistration 界面。
  • ModuleACommonA实现ICommon,其独立注册(IOne:One,ITwo:Two)
  • ModuleBCommonB 实现 ICommon,它的注册(IThree:Three, IFour:Four )

ModuleA这样注册:

public class RegistrationA : ISimpleInjectorRegistration
{
    public void Register(Container container)
    {
        container.Register<IOne, One>();
        container.Register<ITwo, Two>();
        container.Register<ICommon, CommonA>();
        container.RegisterAll<ICommon>(typeof(CommonA));
    }
}

ModuleB这样注册:

public class RegistrationB : ISimpleInjectorRegistration
{
    public void Register(Container container)
    {
        container.Register<IThree, Three>();
        container.Register<IFour, Four>();
        container.Register<ICommon, CommonB>();
        container.RegisterAll<ICommon>(typeof (CommonB));
    }
}

现在,在主模块中,您可以这样做:

var container = new Container();
new ModuleA.RegistrationA().Register(container);
new ModuleB.RegistrationB().Register(container);
container.Verify();

但是 ModuleB 注册失败了,因为 ICommon 在两个注册中都是重复的。

使用Options.AllowOverridingRegistrations:

可以避免重复注册并强制替换为最新的
var container2 = new Container();
container2.Options.AllowOverridingRegistrations = true;
new ModuleA.Registration().Register(container2);
new ModuleB.Registration().Register(container2);
container2.Options.AllowOverridingRegistrations = false;
container2.Verify();

var commonInstance2 = container2.GetInstance<ICommon>();
var commonInstances2 = container2.GetAllInstances<ICommon>();

因此,commonInstance2 将是 CommonB 的实例,而 commonInstances2 将是包含单个 CommonB 实例的 ICommon 序列。

您可能希望将 CommonA 作为 ICommon。或者将 ICommon 的所有实现作为 IEnumerable<ICommon>:

var container3 = new Container();
container3.Options.AllowOverridingRegistrations = true;
new ModuleA.Registration().Register(container3);
new ModuleB.Registration().Register(container3);

// you can choose which ICommon should be registered.
container3.Register<ICommon, ModuleA.CommonA>();

// or collect all implementation of ICommon
// (of course using Assembly.GetTypes() is better solution)
container3.RegisterAll<ICommon>(typeof (ModuleA.CommonA), typeof (ModuleB.CommonB));

container3.Options.AllowOverridingRegistrations = false;
container3.Verify();

var commonInstance3 = container3.GetInstance<ICommon>();
var commonInstances3 = container3.GetAllInstances<ICommon>();

因此,commonInstance3 将成为 CommonA 实例,而 commonInstances3 将同时包含 CommonACommonB 实例。

重点是,注册依赖的时候一定要简单。只有一个地方是理想的,但是如果你有独立的模块并且每个模块都不知道彼此,知道两个模块的 'Main' 应该正确配置注册。