最近我读了很多关于应用程序设计模式的东西:关于 DI、SL 反模式、AOP 等等。原因——我想在设计上做出妥协:松散耦合、干净且易于使用。DI 似乎几乎是一种解决方案,除了一个问题:横切和可选依赖导致构造函数或属性污染。因此,我为此提出了自己的解决方案,我想知道您对此有何看法。
Mark Seemann(DI 书籍的作者和著名的“SL 是反模式”声明的作者)在他的书中提到了一种称为 Ambient Context 的模式。尽管他说他不太喜欢它,但这种模式仍然很有趣:它就像旧的好单例,只是它是作用域的并提供默认值,因此我们不必检查 null。它有一个缺陷——它没有而且它不知道它的范围以及如何处置自己。
那么,为什么不在这里应用服务定位器呢?它可以解决环境上下文对象的作用域和处置问题。在你说它是反模式之前:这是你隐藏合同的时候。但在我们的例子中,我们隐藏了 OPTIONAL 合同,所以 IMO 并没有那么糟糕。
这里有一些代码来说明我的意思:
public interface ILogger
{
void Log(String text);
}
public interface ISomeRepository
{
// skipped
}
public class NullLogger : ILogger
{
#region ILogger Members
public void Log(string text)
{
// do nothing
}
#endregion
}
public class LoggerContext
{
public static ILogger Current
{
get
{
if(ServiceLocator.Current == null)
{
return new NullLogger();
}
var instance = ServiceLocator.Current.GetInstance<ILogger>();
if (instance == null)
{
instance = new NullLogger();
}
return instance;
}
}
}
public class SomeService(ISomeRepository repository)
{
public void DoSomething()
{
LoggerContext.Current.Log("Log something");
}
}
编辑:我意识到不问具体问题与堆栈溢出设计相冲突。因此,我会将一篇最好地描述为什么这种设计不好或更好地提供更好的解决方案(或者可能是添加?)的帖子标记为答案。但是不要建议 AOP,它很好,但是当你真的想在你的代码中做一些事情时,它不是一个解决方案。
编辑 2:我添加了对 ServiceLocator.Current 的检查是否为空。这就是我的代码要做的事情:在未配置 SL 时使用默认设置。