2013-02-06 249 views
1

在Tiny IOC中,如何得到它正在解析的類型。例如日誌記錄:TinyIOC構造函數注入

container.Register<ILogger>((c, p) => 
             { 
              return LoggerFactory.CreateLog(typeofCALLER); 
             }); 

我想添加一個工廠來構建一個ILogger,但沒有注入信息。

+0

您在這裏提供一點背景知識。 LoggerFactory的代碼是什麼樣的,你的意思是什麼樣的「注入信息」?作爲一個黑暗中的鏡頭,我認爲沒有靜態的LoggerFactory(或者至少不是直接在這裏調用)可能會有所幫助。 – TeaDrivenDev

+0

LoggerFactory.CreateLog只是返回一個Ilogger,它是一個靜態的或者是它的完成。我需要注入者的注入信息來填寫typeofCALLER – maxfridbe

+0

我認爲它對我來說意味着什麼 - LoggerFactory返回的實現取決於你想要注入ILogger實例的類,對嗎? – TeaDrivenDev

回答

2

在這種情況下,簡單使用TinyIoC的Open Generics功能可能就足夠了。

public class Consumer 
{ 
    public Consumer(ILogger<Consumer> logger) {} 
} 

public interface ILogger<T> 
{ 
    string Log(string message); 
} 

public class ConcreteLogger<T>:ILogger<T> 
{ 
    public string Log(string message) 
    { 
     return string.Format("{0}: {1}", typeof (T), message); 
    } 
} 

,然後做

container.Register(typeof (ILogger<>), typeof (ConcreteLogger<>)); 

這將導致ConcreteLogger<Consumer>一個實例被注入Consumer構造。

編輯

如果你需要有一個​​參考,你可以簡單地ILogger<T>只是一個「標記接口」,並有來自​​它「導出」:

public interface ILogger<T> : ILogger 
{ 
} 

Consumer類仍然需要依賴ILogger<Consumer>,但ConcreteLogger<T>會直接執行​​成員。

我沒有看到更好的方法,特別是如果​​接口是固定的,因爲它不是你自己的。我不認爲有一種方法可以向TinyIoC詢問它目前正在試圖解決的類型,然後才能夠採取行動,所以如果您需要類型特定的實現,則必須通過其他方式使類型變得通用 - 而泛型常常(並不總是)對此有幫助。

+0

這真棒,有沒有辦法做到這一點,而不必將ILogger轉換爲泛型類型。我不想要這個,因爲我想保持與log4net的記錄器impl兼容。 – maxfridbe

+0

您不需要更改'ILogger',但是如果沒有泛型,您將無法完成。查看更新的答案。 – TeaDrivenDev

+0

如果您嘗試使用它,您可能已經注意到它實際上並不工作。這是因爲TinyIoC在開放泛型方面存在一個錯誤:http://stackoverflow.com/questions/15450518/how-to-register-a-generic-interface-using-tinyioc/15714045 – TeaDrivenDev

1

注意:我在我的示例中使用了ILog,這是log4net將其稱爲類型特定的記錄器類。但它似乎是以與您的示例中的ILogger完全相同的方式創建和使用的,而log4net的LogManager.GetLog(Type t)與您的LoggerFactory.CreateLog(typeofCALLER)類似。

這是一個更多的工作,但您可以創建一個通用的工廠類,生成您的類型特定的記錄器。將此工廠類注入構造函數而不是Ilog

TinyIoC的註冊API不允許您指定一個工廠,它知道當前正在解析的類型被注入到的包含類型。由於TinyIoC注入了LogFactory<Foo>LogFactory<Bar>的正確通用實例,然後我們捕獲了由logFactory.Get()返回的正確生成的ILog實例,因此以下解決方法可行。除了使用autofac做了一些額外的按鍵操作 - 它確實支持你之後的操作 - 但它們並不需要太多的考慮。

假設你想在類FooBar中做一些日誌記錄。您可以定義LogFactory<T>只有一次,而在富,酒吧使用,並要求具有特定類型的ILog實例記錄任何其他類:

public class LogFactory<T> { 
    public LogFactory() {} //empty 
    public ILog Get() { return LogManager.GetLogger(typeof(T)); } 
} 

public class Foo { 
    private readonly ILog _log; 

    public Foo(LogFactory<Foo> logFactory, ...) { 
     _log = logFactory.Get(); 
    } 
} 

public class Bar{ 
    private readonly ILog _log; 

    public Bar(LogFactory<Bar> logFactory, ...) { 
     _log = logFactory.Get(); 
    } 
}