Question

I might be overthinking this. I hope so.

In our .Net 4.5, C# 5 Windows service, we're using Castle Windsor 3.2 with the CollectionResolver installed. We have an interface IEncryptionService that does what you'd expect, and two classes implement that interface. The service needs to integrate and bridge two other systems, by decrypting data from one and re-encrypting it for the other.

Both implementations have names according to their target system.

Component.For<IEncryptionService>()
    .ImplementedBy<System1EncryptionService>()
    .Named("system1-encryption")
    .LifestyleTransient(),
Component.For<IEncryptionService>()
    .ImplementedBy<System2EncryptionService>()
    .LifestyleTransient()
    .Named("system2-encryption"));

The Windows service class uses constructor injection to receive an array of type IEncryptionService[]. Both of the encryption classes are being injected.

Therein lies the problem: I need to use one implementation for one system, and the other for the other. The way I've implemented it thus far, they're indistinguishable from each other.

What is the solution here? A typed factory seems like an anti-pattern covering up an architectural flaw. But its the only thing I've come up with. I've named my components; can I take advantage of that in other components? Or should I just forget injection and instantiate them directly?

I figure this sort of situation happens often enough that there's probably a standard way of handling it.

Was it helpful?

Solution

When you register your component which depends on the two, you specify the names of the arguments corresponding to the injected classes in the Compnent.For line:

Component.For<IServiceUsingTheEncryption>()
    .ImplementedBy<ServiceUsingTheEncryption>()
    //.LifestyleOfYourChoosing
    .ServiceOverrides(
        ServiceOverride.ForKey("encryptionService1").Eq("system1-encryption"),
        ServiceOverride.ForKey("encryptionService2").Eq("system2-encryption"));

And in the ctor of your ServiceUsingTheEncryption, you would specify the arguments as such:

public ServiceUsingTheEncryption(IEncryptionService encryptionService1, IEncryptionService encryptionService2) {
    // ...
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top