How to share instance between decoratee and decorator in the context of ScopedLifestyle.Flowing

主宰稳场 提交于 2021-02-11 12:53:43

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!