我有興趣瞭解更多關於人們如何使用依賴注入平臺注入日誌的知識。雖然下面的鏈接和我的示例都提到了log4net和Unity,但我不一定會使用其中的任何一個。對於依賴注入/ IOC,我可能會使用MEF,因爲這是項目其他部分(大)正在解決的標準。我很新的依賴注入/ ioc,並且對於C#和.NET來說很新(在VC6和VB6的過去10年左右,C#/ .NET中已經寫了很少的生產代碼)。我已經對各種各樣的日誌解決方案進行了很多調查,所以我認爲我對他們的功能集有很好的把握。我只是不太熟悉用實際的機制來獲得一個依賴注入(或者,也許更「正確地」,得到一個注入的依賴注入的抽象版本)。依賴注入和命名記錄器
我已經看到了相關的記錄和/或依賴注入其他職位,如: dependency injection and logging interfaces
What would a Log4Net Wrapper class look like?
again about log4net and Unity IOC config
我的問題沒有專門做「如何使用ioc工具yyy注入日誌記錄平臺xxx?「相反,我感興趣的是人們如何處理包裝日誌平臺(通常,但並不總是推薦)和配置(即app.config)。例如,使用log4net的作爲一個例子,我可以配置(在app.config)中的一些記錄器中,然後在使用這樣的代碼的標準方法得到的那些記錄器(不依賴注入):
private static readonly ILog logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
替代地如果我的記錄是未命名的一類,而是一個功能區域,我可以這樣做:
private static readonly ILog logger = LogManager.GetLogger("Login");
private static readonly ILog logger = LogManager.GetLogger("Query");
private static readonly ILog logger = LogManager.GetLogger("Report");
所以,我想,我的「要求」將是這樣的:
我想將我的產品的來源與日誌平臺的直接依賴關係隔離開來。
我希望能夠通過某種依賴注入(可能是MEF)直接或間接地解析特定的命名記錄器實例(可能在同一命名實例的所有請求者之間共享相同的實例)。
我不知道我是否會稱這是一個困難的要求,但我希望能夠根據需要獲得一個命名記錄器(不同於類記錄器)。例如,我可能會根據班級名稱爲我的班級創建一個記錄器,但是一種方法需要特別嚴格的診斷,我想單獨控制這些診斷。換句話說,我可能希望單個類「依賴」兩個獨立的記錄器實例。
讓我們從數字1開始。我已經閱讀了很多文章,主要是關於stackoverflow,關於它是否是一個好主意換行。請參閱上面的「最佳實踐」鏈接,並轉至jeffrey hantin的評論,以獲取有關爲什麼打包log4net很糟糕的觀點。如果你真的包裝了(如果你能有效地包裝)你會嚴格包裝注入/消除直接歧視的目的?或者你還會嘗試抽象掉一些或全部log4net app.config信息?假設我想要使用System.Diagnostics,我可能想要實現一個基於接口的記錄器(甚至可能使用「常見的」ILogger/ILog接口),可能基於TraceSource,這樣我就可以注入它。您是否會通過TraceSource實現接口,並按原樣使用System.Diagnostics app.config信息?
事情是這樣的:
public class MyLogger : ILogger
{
private TraceSource ts;
public MyLogger(string name)
{
ts = new TraceSource(name);
}
public void ILogger.Log(string msg)
{
ts.TraceEvent(msg);
}
}
而且使用這樣的:
private static readonly ILogger logger = new MyLogger("stackoverflow");
logger.Info("Hello world!")
移動到2號......如何解決一個特定的命名記錄器實例?我是否應該利用我選擇的日誌平臺的app.config信息(即根據app.config中的命名方案解析記錄器)?所以,在log4net的情況下,我可能更喜歡「注入」LogManager(請注意,我知道這是不可能的,因爲它是一個靜態對象)?我可以打包LogManager(稱爲MyLogManager),給它一個ILogManager接口,然後解析MyLogManager.ILogManager接口。我的其他對象可能在ILogManager上有一個依賴關係(用MEF的說法導入)(從它實現的程序集導出)。現在我可以有這樣的對象:
public class MyClass
{
private ILogger logger;
public MyClass([Import(typeof(ILogManager))] logManager)
{
logger = logManager.GetLogger("MyClass");
}
}
任何時候調用ILogManager,它都會直接委託給log4net的LogManager。或者,包裝的LogManager能否根據app.config獲取ILogger實例,並將它們按名稱添加到(a?)MEF容器中。稍後,如果請求具有相同名稱的記錄器,則會爲該名稱查詢包裝的LogManager。如果ILogger在那裏,就這樣解決。如果MEF可以做到這一點,那麼這樣做有沒有什麼好處?
在這種情況下,實際上只有ILogManager是「注入」的,它可以按照log4net的正常方式發出ILogger實例。這種類型的注入(本質上是工廠)與注入指定的記錄器實例相比如何?這確實可以更輕鬆地利用log4net(或其他日誌平臺)app.config文件。
我知道,我能得到命名實例出這樣的MEF容器:
var container = new CompositionContainer(<catalogs and other stuff>);
ILogger logger = container.GetExportedValue<ILogger>("ThisLogger");
但如何獲取命名實例放入容器?我知道基於屬性的模型,我可以有不同的ILogger實現,每個實例都被命名(通過MEF屬性),但這對我沒有任何幫助。有沒有辦法像app.config(或其中的一部分)那樣創建類似於記錄器(所有相同的實現)的名稱,並且MEF可以讀取?可以/應該有一箇中央「管理器」(如MyLogManager),通過底層app.config解析命名的記錄器,然後將解析的記錄器插入到MEF容器中?這樣,對於有權訪問相同MEF容器的其他人可以使用它(儘管沒有MyLogManager瞭解如何使用log4net的app.config信息,似乎該容器將無法直接解析任何指定的記錄器)。
這已經變得很長了。我希望它是連貫的。請隨意分享關於您如何依賴注入日誌平臺的任何特定信息(我們很可能將log4net,NLog或基於System.Diagnostics構建的某些內容(希望很細)考慮到您的應用程序中。
你注入了「管理器」並讓它返回記錄器實例嗎?
您是否在自己的配置部分或DI平臺的配置部分中添加了一些自己的配置信息,以便於/可以直接插入記錄器實例(即使您的依賴項位於ILogger而不是ILogManager上)。
如何讓一個靜態或全局容器具有ILogManager接口或其中的一組命名的ILogger實例。因此,不是按照常規的意義(通過構造函數,屬性或成員數據)進行注入,而是根據需要明確解決日誌依賴性問題。這是依賴注入的好方法還是壞方法?
我把這個標記爲一個社區wiki,因爲它看起來不像一個有明確答案的問題。如果任何人有其他感覺,請隨時更改。
感謝您的幫助!
看起來像MEF和Unity(來自MS的Patterns&Practices組的IoC)就像比較蘋果和橘子。也許一個真正的IoC容器是這個特定問題所需要的,它將具有可擴展性來添加自定義依賴性解決方案。 http://stackoverflow.com/questions/293051/is-mef-a-dependency-injection-framework – 2012-12-28 18:42:31