I'm using Autofac. I'm trying to register 2 classes with same interface using decorator pattern.
public interface IDoable
{
string Do();
}
public class Decoree : IDoable
{
public string Do()
{
return "decoree";
}
}
public class Decorator : IDoable
{
public IDoable InnerDecoree { get; set; }
public Decorator(IDoable doable)
{
this.InnerDecoree = doable;
}
public string Do()
{
return InnerDecoree.Do() + "decorator";
}
}
I'd like to use container for resolving two types for 2 different cases:
IDoable
where I'd expect that instance would be instance of Decorator
Decoree
where I really need to resolve specific Decoree
instance.Only way how I can achieve it is using following code:
[Fact]
public void Both()
{
var builder = new ContainerBuilder();
builder.RegisterType<Decoree>()
.Named<IDoable>("decoree")
.SingleInstance();
builder.RegisterType<Decoree>() // but this is not right I'd like to register it on line above somehow...
.AsSelf()
.SingleInstance();
builder.RegisterType<Decorator>()
.Named<IDoable>("decorator")
.SingleInstance();
builder.RegisterDecorator<IDoable>(
(c, inner) => c.ResolveNamed<IDoable>("decorator", TypedParameter.From(inner)), "decoree")
.As<IDoable>();
var container = builder.Build();
Assert.IsType<Decoree>(container.Resolve<Decoree>());
Assert.False(container.IsRegistered<Decorator>());
Assert.IsType<Decorator>(container.Resolve<IDoable>());
var decoree = container.Resolve<Decoree>();
var decorator = container.Resolve<IDoable>();
var doable = ((Decorator)decorator).InnerDecoree;
Assert.Same(decoree, doable); // FALSE :(
}
The thing is that I'd really love the last assertion to be true :) so It's same instance.
Basically my question is: Is it possible to register type both ways using named and type ?
Because you aren't specifying a scope in your registration, you are getting a different instance of Decoree
every time it gets resolved. I would try something like
builder.RegisterType<Decoree>()
.Named<IDoable>("decoree").SingleInstance();
In addition, you might need to combine your 2 registrations of the Decoree
type:
builder.RegisterType<Decoree>()
.Named<IDoable>("decoree")
.AsSelf()
.SingleInstance();