问题
I don't understand how to to share instance between decoratee and decorator by using a DI container.
The following example illustrates my problem. The context
instance is shared between the TransactionCommandDecorator
and the Command
service.
var context = UowFactory.GetUnitOfWork();
var command = new TransactionCommandDecorator(
context,
new Command(context));
command.Execute(new CommandParams { });
context.dispose();
Basically I need to have a lot of commands that interact with the database and make some call to a repository. I want then to apply a transaction by making use of a decorator that wraps the command service.
The problem is that i don't know how to share the context between the decorator and the decoratee (like in the example) because i need to having a new DbContext
instance for every execution of the command.
Do you explain how i can make this to work by using Simple Injector in the context of Scope flowing (ScopedLifestyle.Flowing
).
This one possible example of implementation of decorator and decoratee
Command Example:
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);
}
Transactional Command decorator:
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();
}
}
}
回答1:
The IUnitOfWork
can be shared between classes with in the same Scope
, by registering it as Lifestyle.Scoped
, as shown in the following example:
container.Register<IUnitOfWork>(() => UowFactory.GetUnitOfWork(), Lifestyle.Scoped);
container.Register<ICommand, Command>();
container.RegisterDecorator<ICommand, TransactionCommandDecorator>();
Usage (using ScopedLifestyle.Flowing):
using (var scope = new Scope(container))
{
ICommand command = scope.GetInstance<ICommand>();
command.Execute(new CommandParams { });
}
Usage (using ambient scoping):
using (AsyncScopedLifestyle.BeginScope(container))
{
ICommand command = container.GetInstance<ICommand>();
command.Execute(new CommandParams { });
}
来源:https://stackoverflow.com/questions/64596241/how-to-share-instance-between-decoratee-and-decorator-in-the-context-of-scopedli