You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
While working with decorators, I'm observing an unexpected change in behavior by adding a Named<TService>(serviceName). It appears that the addition of the named registration is causing the decorators to be applied twice, resuling in D2(D2(D1(D1(root)))) I suspect I may be misunderstanding the interplay between the various registration types.
This seems similar to #965 which was fixed in 4.9.2 per comments in the issue.
Questions
How does adding multiple registrations for the same service impact service resolution?
If this is not a bug, then decorator application appears to be more complex than I anticipated. Is there anything useful that would help me in understanding why autofac behaves the way it does in the below unit tests?
Reproduction
privateinterfaceIContract{IContractInner{get;}}privateclassRoot1:IContract{publicIContractInner=>null;}privateclassDecorator1:IContract{publicIContractInner{get;}publicDecorator1(IContractinner){Inner=inner;}}privateclassDecorator2:IContract{publicIContractInner{get;}publicDecorator2(IContractinner){Inner=inner;}}[Test]publicvoidRegisterType_As_AndRegisterDecorators_AppliesDecoratorsInOrder_ResolvedByType(){// this test passes and produces the following output:// Decorator2// Decorator1// Root1varbuilder=new ContainerBuilder();
builder.RegisterType<Root1>().As<IContract>();
builder.RegisterDecorator(typeof(Decorator1),typeof(IContract));
builder.RegisterDecorator(typeof(Decorator2),typeof(IContract));varcontainer= builder.Build();varcomponent= container.Resolve<IContract>();
WriteInners(component);
Assert.IsInstanceOf<Decorator2>(component);
Assert.IsInstanceOf<Decorator1>(component.Inner);
Assert.IsInstanceOf<Root1>(component.Inner.Inner);}[Test]publicvoidRegisterType_Named_As_AndRegisterDecorators_AppliesDecoratorsInOrder_ResolvedByType(){// this test fails and produces the following output:// Decorator2// Decorator2// Decorator1// Decorator1// Root1varbuilder=new ContainerBuilder();
builder.RegisterType<Root1>().Named<IContract>("root1").As<IContract>();
builder.RegisterDecorator(typeof(Decorator1),typeof(IContract));
builder.RegisterDecorator(typeof(Decorator2),typeof(IContract));varcontainer= builder.Build();varcomponent= container.Resolve<IContract>();
WriteInners(component);
Assert.IsInstanceOf<Decorator2>(component);
Assert.IsInstanceOf<Decorator1>(component.Inner);
Assert.IsInstanceOf<Root1>(component.Inner.Inner);}[Test]publicvoidRegisterType_Named_AndRegisterDecorators_AppliesDecoratorsInOrder_ResolvedByName(){// this test passes and produces the following output:// Decorator2// Decorator1// Root1varbuilder=new ContainerBuilder();
builder.RegisterType<Root1>().Named<IContract>("root1");
builder.RegisterDecorator(typeof(Decorator1),typeof(IContract));
builder.RegisterDecorator(typeof(Decorator2),typeof(IContract));varcontainer= builder.Build();varcomponent= container.ResolveNamed<IContract>("root1");
WriteInners(component);
Assert.IsInstanceOf<Decorator2>(component);
Assert.IsInstanceOf<Decorator1>(component.Inner);
Assert.IsInstanceOf<Root1>(component.Inner.Inner);}[Test]publicvoidRegisterType_Named_As_AndRegisterDecorators_AppliesDecoratorsInOrder_ResolvedByName(){// this test fails and produces the following output:// Decorator2// Decorator2// Decorator1// Decorator1// Root1varbuilder=new ContainerBuilder();
builder.RegisterType<Root1>().Named<IContract>("root1").As<IContract>();
builder.RegisterDecorator(typeof(Decorator1),typeof(IContract));
builder.RegisterDecorator(typeof(Decorator2),typeof(IContract));varcontainer= builder.Build();varcomponent= container.ResolveNamed<IContract>("root1");
WriteInners(component);
Assert.IsInstanceOf<Decorator2>(component);
Assert.IsInstanceOf<Decorator1>(component.Inner);
Assert.IsInstanceOf<Root1>(component.Inner.Inner);}[Test]publicvoidRegisterType_Keyed_As_AndRegisterDecorators_AppliesDecoratorsInOrder_ResolvedByType(){// this test fails and produces the following output:// Decorator2// Decorator2// Decorator1// Decorator1// Root1varbuilder=new ContainerBuilder();
builder.RegisterType<Root1>().Keyed<IContract>("root1").As<IContract>();
builder.RegisterDecorator(typeof(Decorator1),typeof(IContract));
builder.RegisterDecorator(typeof(Decorator2),typeof(IContract));varcontainer= builder.Build();varcomponent= container.Resolve<IContract>();
WriteInners(component);
Assert.IsInstanceOf<Decorator2>(component);
Assert.IsInstanceOf<Decorator1>(component.Inner);
Assert.IsInstanceOf<Root1>(component.Inner.Inner);}[Test]publicvoidRegisterType_Named_Keyed_As_AndRegisterDecorators_AppliesDecoratorsInOrder_ResolvedByType(){// this test fails and produces the following output:// Decorator2// Decorator2// Decorator1// Decorator1// Root1varbuilder=new ContainerBuilder();
builder.RegisterType<Root1>().Named<IContract>("root1").Keyed<IContract>("root1").As<IContract>();
builder.RegisterDecorator(typeof(Decorator1),typeof(IContract));
builder.RegisterDecorator(typeof(Decorator2),typeof(IContract));varcontainer= builder.Build();varcomponent= container.Resolve<IContract>();
WriteInners(component);
Assert.IsInstanceOf<Decorator2>(component);
Assert.IsInstanceOf<Decorator1>(component.Inner);
Assert.IsInstanceOf<Root1>(component.Inner.Inner);}privatevoidWriteInners(IContractcomponent){varcurrent= component;do{
Console.WriteLine(current.GetType().Name);current= current.Inner;}while(current!=null);
The text was updated successfully, but these errors were encountered:
Version Information
Description
While working with decorators, I'm observing an unexpected change in behavior by adding a
Named<TService>(serviceName)
. It appears that the addition of the named registration is causing the decorators to be applied twice, resuling inD2(D2(D1(D1(root))))
I suspect I may be misunderstanding the interplay between the various registration types.This seems similar to #965 which was fixed in
4.9.2
per comments in the issue.Questions
Reproduction
The text was updated successfully, but these errors were encountered: