变量嵌套依赖项的问题
在这种情况下,一个例子胜过千言万语:
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.
}
每个 IProvider
实现都应该依赖于 ProviderSettings,因为这允许我们在不对应用程序进行任何更改的情况下切换提供程序。
我们将默认的 ProviderSettings
连接为 ContextualProviderSettings
。正如您可能猜到的,这个集合是基于上下文的Name
,比如说当前用户的名字。
然而,在某些情况下我们想要使用SystemProviderSettings
。通常这是针对特定服务的:
public class SomeSystemService : ISomeService {
public SomeSystemService(IProvider provider) {
// I need a provider scoped for the "system"
}
}
然后我需要使用我的 DI 工具(StructureMap)连接这些依赖项:
For<ISomeService>().Use<SomeService>()
.Ctor<IStorageProvider>()
.Is(ctx => ctx.GetInstance<IStorageProvider>... this feels wrong
所以我认为这可以通过更好的方式来完成。我尝试了装饰器模式,但我不想装饰特定的 IProvider
实现。这个想法是有一个 SystemProvider
来包装任何已配置为默认 IProvider
的内容。
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 take 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
.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
令人惊奇的是,一夜的睡眠会带来什么。
简单的解决方案,使用工厂:
我可以为每个提供程序实现创建一个工厂,并在运行时传入相关的 ProviderSettings。
Amazing what a nights sleep will do.
Simple solution, use a factory:
I can create a factory for each provider implementation and pass in the relevant ProviderSettings at run time.