c#-Autofac模块应该注册自己的从属模块吗?

考虑一下我有一个使用三个库lib1,lib2和lib3的应用程序.在每个库中,我都实现了一个模块,该模块注册了在该库中实现的依赖项.

这些实现中的某些实现具有自己的依赖关系,例如,lib2和lib3可能都需要lib1中存在的某些实现.

我的问题是,是否让lib2和lib3中的模块在lib1中注册模块作为其Load实现的一部分?如果我的应用程序注册了lib2和lib3的模块,这是否将两次注册该模块?

还是我不让一个模块注册另一个模块,而将其留给应用程序,其缺点是启动时可能会丢失一些注册?

解决方法:

我知道有点晚了,但是我认为回答这个问题可能会更好,而不是仅仅引用关于多重合成根是多么邪恶的经文…

Is this going to register that module twice if my app registers the modules of lib2 and lib3?

使用Autofac 4.8.1进行了测试,它可以:

public class Lib1Module: Module
{
    protected override void Load(ContainerBuilder builder)
    {
        Console.WriteLine("Registering Lib1Module");

        // Register Types...

    }
}

public class Lib2Module: Module
{
    protected override void Load(ContainerBuilder builder)
    {
        Console.WriteLine("Registering Lib2Module");

        builder.RegisterModule<Lib1Module>();

        // Register Types...

    }
}

public class Lib3Module: Module
{
    protected override void Load(ContainerBuilder builder)
    {
        Console.WriteLine("Registering Lib3Module");

        builder.RegisterModule<Lib1Module>();

        // Register Types...

    }
}

public class Program
{
    public void Main(string[] args)
    {
        var builder = new ContainerBuilder();
        builder.RegisterModule<Lib2Module>();
        builder.RegisterModule<Lib3Module>();

        using(var container = builder.Build())
        {
            // Do Stuff
        }
    }
}

输出:

Registering Lib2Module
Registering Lib1Module
Registering Lib3Module
Registering Lib1Module

您可以在IComponentRegistry / ContainerBuidler上使用“属性”字典(“模块”基类在内部创建要传递给Load的“容器”构建器,其中包含来自IComponentRegistry的属性-source)来解决此问题并强制模块进行单次注册(如果Load方法为Lib1Module更改为:

protected override void Load(ContainerBuilder builder)
{
    if (builder.Properties.ContainsKey(GetType().AssemblyQualifiedName))
    {
        return;
    }
    builder.Properties.Add(GetType().AssemblyQualifiedName, null);

    Console.WriteLine("Registering Lib1Module");

    // Register Types...

}

然后输出变为:

Registering Lib2Module
Registering Lib1Module
Registering Lib3Module

显然,如果Lib2Module / Lib3Module然后可以成为其他模块的依赖项,则必须将类似的代码放入其Load方法中,并且类似地,如果任何模块使用AttachToRegistrationSource和/或AttachToComponentRegistration并希望确保仅在需要检查时才运行它们, .另外(可能最好是如果需要做很多事情),您可以创建自己的实现IModule的类,并在Configure中进行检查.

我肯定在生产代码中使用了这种模式,以减少重复的次数,因为我有多个输入点,它们具有自己的合成根(例如,Web API,Web应用程序和循环控制台应用程序),但是它们共享很大的块代码,我可以忍受这一点,这使我成为DI纯粹主义者中不受欢迎的角色.

上一篇:c#-构造函数注入Autofac的InstancePerDependency的生存期


下一篇:C#使用动态构造的事件处理程序处理DDD域事件