问题描述
我不明白如何使用DI容器在decoratee和decorator之间共享实例。
以下示例说明了我的问题。 context
实例在TransactionCommandDecorator
和Command
服务之间共享。
var context = UowFactory.GetUnitOfWork();
var command = new TransactionCommandDecorator(
context,new Command(context));
command.Execute(new CommandParams { });
context.dispose();
基本上,我需要有许多与数据库交互并调用存储库的命令。然后,我想通过使用包装命令服务的装饰器来应用事务。
问题是我不知道如何在装饰者和被装饰者之间共享上下文(例如在示例中),因为每次执行命令都需要有一个新的DbContext
实例。 / p>
您是否解释了如何在范围流动(ScopedLifestyle.Flowing
)的上下文中使用Simple Injector使其工作。
这个装饰器和被装饰者实现的可能例子
命令示例:
public Command(IUnitOfWork uow) => _uow = uow;
public DbResult Execute(CommandParams args)
{
_uow.Repo1.Add(args.Item);
_uow.Repo1.Add(args.Item2);
_uow.Repo1.Remove(args.Item3);
}
事务命令装饰器:
public class TransactionCommandDecorator : ICommand
{
public TransactionCommandDecorator(IUnitOfWork uow,ICommand command)
{
_uow = uow;
_command = command;
}
public DbResult Execute(commandParams args)
{
try
{
var transaction = _uow.GetContext().Database.GetTransaction();
var ret = _command.Execute(args);
if (!ret.Success)
{
transaction.discard();
return;
}
transaction.Commit();
}
catch
{
transaction.discard();
}
finally
{
transaction.dispose();
}
}
}
解决方法
通过将IUnitOfWork
注册为Scope
,可以在具有相同Lifestyle.Scoped
的类之间共享container.Register<IUnitOfWork>(() => UowFactory.GetUnitOfWork(),Lifestyle.Scoped);
container.Register<ICommand,Command>();
container.RegisterDecorator<ICommand,TransactionCommandDecorator>();
,如以下示例所示:
using (var scope = new Scope(container))
{
ICommand command = scope.GetInstance<ICommand>();
command.Execute(new CommandParams { });
}
用法(使用ScopedLifestyle.Flowing):
using (AsyncScopedLifestyle.BeginScope(container))
{
ICommand command = container.GetInstance<ICommand>();
command.Execute(new CommandParams { });
}
用法(使用环境范围界定):
Add id:12 name:"Sandik" singer:"Muslum Gurses" year:2009 count:5 price:20