2017-02-14 2 views
3

同じインタフェース(IAnimal)の2つのわずかに異なる実装をとるコンストラクタ(AnimalHandler)があります。 Simple Injectorを使用して、どのようにして両方の実装を自動的に飾ることができますか?Simple Injectorの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(); 
} 

私は装飾が起こることができるようにインターフェイスがコンストラクタで使用されるべきであることを理解します。私はthusly AnimalInterfaceHandlerICat、およびIDogを作成します。

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()); 

アサートに失敗しました。 が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

脆いようですが、 'CatBase'に' Cat 'をリファクタリングする場合に '.Verify()'が警告されるはずです。あなたの答えは私の非おもちゃの問題を解決しますが、特に複数のインタフェースを持つ実装の場合、デコレータが 'RegisterCollection'に適用されないことが期待されますか?おかげさまで、SIは素晴らしい図書館です! – DharmaTurtle

+0

私はおそらくあなたの 'RegisterConditional'ソリューションを私のハッキー' RegisterCollection'よりも選択するでしょう。なぜなら、 'ICat'と' IDog'を作成する必要がないからです。私はそれぞれの具体的な実装をマークするためのインターフェースを作成しなければならないと馬鹿げている。 – DharmaTurtle

関連する問題