2017-02-14 72 views
3

我有一个构造函数(AnimalHandler),它采用了两个稍微不同的实现相同的接口(IAnimal)。使用简单的喷油器,我怎么能自动装饰这两个实现?使用简单注入器的RegisterCollection注册的实现没有装饰

一个例子年表:

interface IAnimal { 
    string Speak(); 
} 
class Cat : IAnimal{ 
    public string Speak() => "Meow"; 
} 
class Dog : IAnimal{ 
    public string Speak() => "Woof"; 
} 
class AnimalSpeakLoudlyDecorator : IAnimal { 
    private readonly IAnimal _decorated; 
    public AnimalSpeakLoudlyDecorator(IAnimal decorated) { 
    _decorated = decorated; 
    } 
    public string Speak() => _decorated.Speak().ToUpper(); 
} 
class AnimalHandler { 
    private readonly Cat _cat; 
    private readonly Dog _dog; 
    public AnimalHandler(Cat cat, Dog dog) { 
    _cat = cat; 
    _dog = dog; 
    } 
    public string HandleCat() => _cat.Speak(); 
    public string HandleDog() => _dog.Speak(); 
} 

在这里,我认识到,接口应在构造函数中使用,以便装修可能发生。我正是如此创建AnimalInterfaceHandlerICatIDog

interface ICat : IAnimal { } 
interface IDog : IAnimal { } 
class Cat : ICat {...} 
class Dog : IDog {...} 
class AnimalInterfaceHandler { 
    private readonly ICat _cat; 
    private readonly IDog _dog; 
    public AnimalInterfaceHandler(ICat cat, IDog dog) { 
    _cat = cat; 
    _dog = dog; 
    } 
    public string HandleCat() => _cat.Speak(); 
    public string HandleDog() => _dog.Speak(); 
} 

register multiple interfaces with the same implementation

var container = new Container(); 
var catRegistration = Lifestyle.Singleton.CreateRegistration<Cat>(container); 
container.AddRegistration(typeof(ICat), catRegistration); 
var dogRegistration = Lifestyle.Singleton.CreateRegistration<Dog>(container); 
container.AddRegistration(typeof(IDog), dogRegistration); 
container.RegisterCollection<IAnimal>(new[] { catRegistration, dogRegistration }); 
container.RegisterDecorator(typeof(IAnimal), typeof(AnimalSpeakLoudlyDecorator), Lifestyle.Singleton); 
container.Verify(); 
var handler = container.GetInstance<AnimalInterfaceHandler>(); 
Assert.AreEqual("MEOW", handler.HandleCat()); 

断言失败;尽管IAnimal已注册RegisterCollection,但装饰者不适用。有任何想法吗?

回答

1

这应该做的伎俩:

var container = new Container(); 

container.RegisterConditional<IAnimal, Cat>(c => c.Consumer.Target.Name == "cat"); 
container.RegisterConditional<IAnimal, Dog>(c => c.Consumer.Target.Name == "dog"); 

container.RegisterDecorator(typeof(IAnimal), typeof(AnimalSpeakLoudlyDecorator)); 

container.Verify(); 

该注册利用了RegisterConditional方法,它允许进行基于对消费者信息的条件或上下文登记。在这种情况下,它使用它被注入的构造函数参数的名称。

+0

它似乎是一个触摸脆弱的,但是'.Verify()'应该在我重构'Cat'到CatBase'的时候提醒我。虽然你的答案确实解决了我的非玩具问题,但是它是否会期望装饰器不适用于'RegisterCollection',特别是在具有多个接口的实现中?非常感谢,SI是一个很棒的图书馆! – DharmaTurtle

+0

无论如何,我可能会选择你的'RegisterConditional'解决方案来处理我的hacky'RegisterCollection',因为这意味着我不必创建'ICat'和'IDog'。有点傻,我必须创建一个界面来标记每个具体的实现。 – DharmaTurtle