In this case an example is worth a thousand words:
interface IProvider {
}
class DefaultProvider : IProvider {
private readonly ProviderSettings settings;
public DefaultProvider(ProviderSettings settings) {
this.settings = settings;
}
}
class ProviderSettings {
string Name { get; set;}
}
class SystemProviderSettings : ProviderSettings {
public SystemProviderSettings() {
this.Name = "System";
}
}
class ContextualProviderSettings : ProviderSettings {
// etc.
}
Each IProvider
implementation should tak开发者_运维问答e a ctor dependency on ProviderSettings, as this is what allows us to switch providers without making any changes to our application.
We wire up the default ProviderSettings
to be ContextualProviderSettings
. As you might guess, this set's the Name
based on something contextual, let's say the current user's name.
However, in some cases we want to use SystemProviderSettings
. Usually this is for a specific service:
public class SomeSystemService : ISomeService {
public SomeSystemService(IProvider provider) {
// I need a provider scoped for the "system"
}
}
I then have a bit of a job wiring up these dependencies with my DI tool (StructureMap):
For<ISomeService>().Use<SomeService>()
.Ctor<IStorageProvider>()
.Is(ctx => ctx.GetInstance<IStorageProvider>... this feels wrong
So I think that this can be done in a better way. I tried the decorator pattern but I don't want to decorate a specific IProvider
implementation. The idea would be to have a SystemProvider
that wraps whatever has been configured as the default IProvider
.
Amazing what a nights sleep will do.
Simple solution, use a factory:
public class IProviderFactory {
IProvider Create(ProviderSettings settings);
}
I can create a factory for each provider implementation and pass in the relevant ProviderSettings at run time.
精彩评论