Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Autofac Open Generic Decorator with multiple interface causes circular dependency resolving

I have the following interfaces :

public interface ICommandHandler<T>
{
    void Handle(T command);
}

public class TransactionalCommandHandlerDecorator<T> : ICommandHandler<T>
{
    private readonly ICommandHandler<T> _handler;
    public TransactionalCommandHandlerDecorator(ICommandHandler<T> handler)
    {
        _handler = handler;
    }
    public void Handle(T command)
    {
    }
}

and I have a concrete class which implementing two command handlers :

public class Handler : ICommandHandler<CreateLocation>
                        ,ICommandHandler<ModifyLocation>
{
    public void Handle(CreateLocation command)
    {

    }

    public void Handle(ModifyLocation command)
    {
    }
}

and I have a registration as following :

 builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly())
            .AsClosedTypesOf(typeof(ICommandHandler<>))
            .InstancePerLifetimeScope();

    builder.RegisterGenericDecorator(typeof(TransactionalCommandHandlerDecorator<>), typeof(ICommandHandler<>));

Resolving 'Handler' class causes autofac to circularly resolving decorater and handler in an infinite loop which causes a StackOverflowException. if I a change 'Handler' to implement only one interface, then it will works without problem.

any idea on how to fix that?

like image 894
Hadi Ahmadi Avatar asked Sep 06 '25 03:09

Hadi Ahmadi


1 Answers

This is a bug and will be addressed in a future release of Autofac. The fix looks like it will require a breaking change to another part of the API so will need to be released as part of v5.0.

In the meantime, one way to work around the issue is creating separate registrations.

var builder = new ContainerBuilder();
builder.RegisterType<Handler>().As<ICommandHandler<CreateLocation>>();
builder.RegisterType<Handler>().As<ICommandHandler<ModifyLocation>>();
builder.RegisterGenericDecorator(typeof(TransactionalCommandHandlerDecorator<>), typeof(ICommandHandler<>));
var container = builder.Build();

var instance = container.Resolve<ICommandHandler<CreateLocation>>();
like image 175
Alex Meyer-Gleaves Avatar answered Sep 07 '25 23:09

Alex Meyer-Gleaves