【问题标题】:How to configure Simple Injector to implement command handler pattern inside a context transaction如何配置简单注入器以在上下文事务中实现命令处理程序模式
【发布时间】:2020-10-02 15:36:37
【问题描述】:

我正在尝试在 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 容器中注册所有类来实现这一点。 也许我的命令处理程序设计或使用 DI 有问题。

您能给我举个例子或以正确的方式引导我吗?

提前致谢

【问题讨论】:

    标签: c# design-patterns dependency-injection inversion-of-control simple-injector


    【解决方案1】:

    Simple Injector 允许自动注册泛型类型,例如您的命令处理程序。只需调用Container.Register,即可注册所有命令处理程序:

    container.Register(typeof(IDatabaseCommand<,>), typeof(BusinessCommand).Assembly);
    

    之后,你就可以一一注册你的装饰器了:

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

    请注意,此类装饰器在泛型类型时效果最佳,因为在这种情况下,Simple Injector 可以将其包装在任意IDatabaseCommand&lt;,&gt; 实现周围。

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

    【讨论】:

    • 感谢@Steven,这非常有用,我将尝试实现它。但我不明白的是如何将命令实际注入 BusinessCase 类。如果我使用构造函数注入,我什至需要注册 DbContext,但如果我注入它,我将如何控制 dbcontext 的生命周期?
    • 我需要的是为每个由命令处理程序实现的业务案例提供一个范围内的 Dbcontext ......你能给我一些例子吗?
    • 查看ScopedCommandHandlerProxy&lt;T&gt; 文档部分中的ScopedCommandHandlerProxy&lt;T&gt;
    • Thk,这就是我要找的。非常感谢!!!!!!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-03
    • 1970-01-01
    • 1970-01-01
    • 2023-03-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多