最近我讀了很多關於應用程序設計模式的東西:關於DI,SL反模式,AOP等等。其原因 - 我想達成設計的妥協:鬆散耦合,乾淨,易於使用。除了一個問題之外,DI似乎幾乎是一種解決方案:跨領域和可選的依賴導致構造或財產污染。所以我來爲我自己的解決方案和我想知道你怎麼看它。依賴注入+環境上下文+服務定位器
Mark Seemann(DI書的作者,着名的「SL is anti-patter」聲明)在他的書中提到了一種叫做Ambient Context的模式。雖然他說他不太喜歡它,但這種模式仍然很有趣:它就像舊的單身人士,除了它是作用域並提供默認值的,所以我們不必檢查null。它有一個缺陷 - 它沒有,它不知道它的範圍和如何處理它自己。
那麼,爲什麼不在這裏應用服務定位器?它可以解決範圍和處理環境上下文對象的問題。在你說它是反模式之前:這是你隱藏合約的時候。但在我們的情況下,我們隱藏可選合約,所以它不是那麼糟糕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時使用默認設置。
我從你的問題中遺漏了一個例子,你清楚地表明你需要使用'LoggerContext.Current'而不是在代碼中注入一個'ILogger'。根據我的經驗,如果您需要在代碼中注入許多'ILogger'依賴項,您要麼記錄太多(而不是拋出異常),或者您沒有遵守SRP(實際上您需要AOP)。看看這個答案:http://stackoverflow.com/questions/9892137/windsor-pulling-transient-objects-from-the-container。 – Steven