0

我基于 Tripod 和其他灵感开发了一个 CQRS 风格的数据库访问框架,但针对 .NET Standard 并进行了简化以便于使用。我想将 IoC 拆分为单独的集成包,以便消费者可以轻松地获得我目前在内部进行的类型注册,而不会被锁定到特定的 IoC 容器中。我的问题是我只与 SimpleInjector 密切合作,因此不熟悉其他系统及其处理特定场景的细微差别。我迫切需要支持 Autofac,所以我想我会在这里尝试看看是否有人可以翻译。

我有以下 Simple Injector CompositionRoot 静态类:

public static void RegisterDatabase(this Container container, DbContextOptions<EntityDbContext> dbContextOptions, params Assembly[] assemblies)
{
    var scopedLifeStyle = container.Options.DefaultScopedLifestyle;

    //container.Register<ICreateDbModel, DefaultDbModelCreator>(scopedLifeStyle); // lifestyle c
    container.RegisterInitializer<EntityDbContext>( //(container.InjectProperties);
        handlerToInitialise => handlerToInitialise.ModelCreator = new DefaultDbModelCreator()
    );

    // Setup DbContext
    var ctxReg = scopedLifeStyle.CreateRegistration(
        () => new EntityDbContext(dbContextOptions),
        container);

    container.AddRegistration<IUnitOfWork>(ctxReg);
    container.AddRegistration<IReadEntities>(ctxReg);
    container.AddRegistration<IWriteEntities>(ctxReg);
}

在 ASP.NET Core 解决方案中,我从 Startup.Configure(...) 调用上述内容:

var optionsBuilder = new DbContextOptionsBuilder<EntityDbContext>()
    //.UseInMemoryDatabase("Snoogans");
    .UseSqlServer(_config.GetConnectionString("DefaultConnection"));
container.RegisterDatabase(optionsBuilder.Options);

如果需要,这允许我切换到内存数据库进行单元测试。EntityDbContext 包含我所有用于调用上下文的工作单元方法,而无需为每个表指定显式 DbSet。IUnitOfWork、IReadEntities 和 IWriteEntities 接口都在 EntityDbContext 上定义方法。

因此,我不确定如何制作一个 Autofac 模块,该模块允许通过传入 DbContextOptions 对 dbcontext 进行范围注册,然后对该注册进行多个接口注册。

有谁知道如何做到这一点?

4

1 回答 1

0

我制定了这个过程,现在有了一个 AutoFac 模块。我能够通过类的实例注册模块,并在实例化时传递选项。因为 EntityDbContext 实现了我在 Simple Injector 场景中分别注册的三个接口,所以 AutoFac 可以方便地推断它们并使用 AsImplementedInterfaces() 注册

public class EntityFrameworkModule : Module
    {
        private readonly DbContextOptions<EntityDbContext> _dbContextOptions;

        public EntityFrameworkModule(DbContextOptions<EntityDbContext> dbContextOptions)
        {
            _dbContextOptions = dbContextOptions;

        }

        protected override void Load(ContainerBuilder builder)
        {
            // If the calling code hasn't already registered a custom 
            // ICreateDbModel then register the internal DefaultDbModelCreator
            builder.RegisterType<DefaultDbModelCreator>()
                .IfNotRegistered(typeof(ICreateDbModel))
                .As<ICreateDbModel>();

            // Expecting IUnitOfWork, IReadEntities and IWriteEntities to be registered with this call
            builder.Register(c => new EntityDbContext(_dbContextOptions)
                {
                    ModelCreator = c.Resolve<ICreateDbModel>()
                })
                .AsImplementedInterfaces()
                .InstancePerLifetimeScope();

        }
    }
于 2020-06-24T07:33:45.150 回答