2013-02-06 199 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(); 
    } 
}