如何配置简单注入器以在上下文事务中实现命令处理程序模式
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<,>
实现周围。
有关注册泛型类型和装饰器的更多信息,请阅读我们的精美文档:
我正在尝试在 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<,>
实现周围。
有关注册泛型类型和装饰器的更多信息,请阅读我们的精美文档: