如何配置简单注入器以在上下文事务中实现命令处理程序模式

How to configure Simple Injector to implement command handler pattern inside a context transaction

我正在尝试在 WPF 应用程序上应用命令处理程序模式。

我在理解如何配置 IoC 容器(在我的例子中我使用 Simple Injector)以拥有这种功能时遇到了一些问题。

我想执行一个数据库命令处理程序(在 DbContext 上执行一些操作)并且每个命令都必须包含在同一上下文中创建的事务中。

类似这样(这只是一个例子)


public class BusinessUseCases
{
    public void BusinessCase1()
    {
        BusinessCommandParams1 commandParams = new BusinessCommandParams1();

        using (var db = new DbContext(connectionString))
        {
            IDatabaseCommand<DatabaseResult, BusinessCommandParams1> databaseCreate =
                new TransactionDatabaseCommandDecorator(new BusinessCommand(db), db);

            databaseCreate.Execute(commandParams);
        }
    }

    ....

    Other business case
}

public interface IDatabaseCommand<TResult, TParam>
{
    TResult Execute(TParam commandParam);
}

public class BusinessCommandParams1
{
    //some property
}

public class DatabaseResult
{
    //some property
}
public class BusinessCommand : IDatabaseCommand<DatabaseResult, BusinessCommandParams1>
{
    private readonly DbContext _context;

    public BusinessCommand(IDbContext context)
    {
        _context = context;
    }

    public DatabaseResult Execute(BusinessCommandParams1 commandParam)
    {
        //use context
        return new DatabaseResult();
    }
}

public class TransactionDatabaseCommandDecorator : IDatabaseCommand<DatabaseResult, BusinessCommandParams1>
{
    private readonly IDatabaseCommand<DatabaseResult, BusinessCommandParams1> _command;
    private readonly DbContext _context;

    public TransactionDatabaseCommandDecorator(IDatabaseCommand<DatabaseResult, BusinessCommandParams1> command, DbContext context)
    {
        _command = command;
        _context = context;
    }

    public DatabaseResult Execute(BusinessCommandParams1 commandParam)
    {
        using (var transaction = _context.Database.BeginTransaction())
        {
            try
            {
                _command.Execute(commandParam);
                transaction.Commit();
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                transaction.Discard();
                throw;
            }
        }
    }
}

所以基本上我需要通过使用 POOR MAN DI 来实现类似的东西

public class BusinessUseCases
{
    public void BusinessCase1()
    {
        BusinessCommandParams1 commandParams = new BusinessCommandParams1();


        using (var db = new DbContext(connectionString))
        {
            IDatabaseCommand<DatabaseResult, BusinessCommandParams1> databaseCreate =
                new TransactionDatabaseCommandDecorator(new BusinessCommand(db), db);

            databaseCreate.Execute(commandParams);
        }
    }

    ....

    Other business case
}

使用简单的注入器甚至另一个 IOC 容器。

我需要的是用包含在单个作用域 DbContext 中的业务案例逻辑来实现命令处理程序。 为了更好地解释,我需要从容器中获取正确的命令处理程序,该处理程序在定义明确的 Dbcontext 中执行其逻辑,该 Dbcontext 将在执行后进行处理。

但我不明白如何通过在 ioc 容器中注册所有 class 来实现这一点。 也许我的命令处理程序设计或使用 DI 有问题。

能否请您举个例子或以正确的方式指导我?

提前致谢

Simple Injector 允许 Auto-Registration 通用类型,例如您的命令处理程序。只需调用 Container.Register:

即可注册所有命令处理程序
container.Register(typeof(IDatabaseCommand<,>), typeof(BusinessCommand).Assembly);

之后,您可以一一注册您的装饰器:

container.RegisterDecorator(
    typeof(IDatabaseCommand<,>),
    typeof(TransactionDatabaseCommandDecorator));

请注意,这种装饰器在它是泛型类型时效果最好,因为在那种情况下,Simple Injector 可以将其包装在任意 IDatabaseCommand<,> 实现周围。

有关注册泛型类型和装饰器的更多信息,请阅读我们的精美文档: