Multiple Decorator pattern in castle-windsor
Asked Answered
E

1

14

We are in the process of redesigning some legacy software to be more testable and have decided upon Dependency-Injection and Castle.Windsor to help us.

First, our goal: * A number of decorators that all work on a data stream. * Multiple combinations of the decorators are possible and the root nodes in each case can be required to get data from different places.

Technically, our design is as follows:

interface IUpdateableValue<T> 
{
  T Get();
};

We have e.g. three sets of data to be retrieved with a number of components, all implementing IUpdateableValue() (Pseudo-code):

JsonParser(
    Decompressor(
        Decrypter(decryptionKey
            FileCache(filename, 
                HttpWebDownloader(url))))

XmlParser(
    Decompressor(
        Decrypter(decryptionKey2
            FileCache(filename2, 
                HttpWebDownloader(url2))))

I'm having trouble getting out design to fit into a DI-framework like Castle-Windsor. I suspect some of it could be handled by named instances, but this seems smelly for this usage.

The idea is that the "user" of e.g. the JsonParser and XmlParser instances don't know (or care) whether data comes from a HttpUrl, a file or magically pulled out of a hat.

I'm thinking there is something wrong in our design, but unsure how to fix it.

Any ideas on how to progress?

Equipage answered 25/5, 2012 at 13:59 Comment(2)
There are questions about working with generic decorators in Windsor here on SO (such as this one), but I can't remember any one being answered, so I expect this to be hard to do with Windsor. Other containers, such as Autofac or Simple Injector, might yield more success. Perhaps this wiki page about registering generic decorators in Simple Injector might give you some ideas about how to design your system.Agonized
Why would you use Castle for this? What benefits will it provide?Poling
P
19

With Castle Windsor you can implicitly configure decoraters by registering them in the correct order. You need to register the outer decorater first:

container.Register(Component
  .For<IUpdateableValue>()
  .ImplementedBy<JsonParser>());
container.Register(Component
  .For<IUpdateableValue>()
  .ImplementedBy<Decompressor>());
container.Register(Component
  .For<IUpdateableValue>()
  .ImplementedBy<Decrypter>());
...

When you resolve IUpdateableValue Caste Windsor will automatically wire up the dependencies, so they are nested correctly.

Pabulum answered 29/5, 2012 at 22:13 Comment(1)
As a side note: There is IsDefault which will instruct windsor to resolve a specific component by default. Then the order of registration doesn't matter.Bernice

© 2022 - 2024 — McMap. All rights reserved.