【问题标题】:TinyIOC constructor injectionTinyIOC 构造函数注入
【发布时间】:2015-03-20 16:06:34
【问题描述】:

在 Tiny IOC 中,如何获得正在解析的类型。例如日志记录:

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

我正在尝试添加工厂来构建 ILogger,但没有注入信息。

【问题讨论】:

  • 您在这里提供的上下文很少。 LoggerFactory的代码是什么样子的,你指的是什么“注入信息”?作为一个在黑暗中的镜头,我认为没有静态的LoggerFactory(或者至少不直接在这里调用它)可能会有所帮助。
  • LoggerFactory.CreateLog 只返回一个 Ilogger,它是静态的,或者它已经完成。我需要被注射者的注射信息来填写 typeofCALLER
  • 我想我明白你的意思了 - LoggerFactory 返回的实现取决于你想要注入 ILogger 实例的类,对吧?
  • 所以 ILogger.Log("blah") 将逐字附加到 log.txt “typeofCALLER time blah”,所以当我构建 ILogger 时,它需要知道 typeofCALLER 是什么才能记录.

标签: .net dependency-injection tinyioc


【解决方案1】:

在这种情况下,简单地使用 TinyIoC 的开放泛型功能可能就足够了。

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&lt;Consumer&gt; 的实例被注入Consumer 构造函数。

编辑

如果你需要一个ILogger 引用,你可以简单地将ILogger&lt;T&gt; 设置为一个“标记接口”,并让它从ILogger“派生”:

public interface ILogger<T> : ILogger
{
}

Consumer 类仍需要依赖于 ILogger&lt;Consumer&gt;,但 ConcreteLogger&lt;T&gt; 将直接实现 ILogger 成员。

我认为没有更好的方法,特别是如果ILogger 接口是固定的,因为它不是你自己的。我认为没有办法向 TinyIoC 询问它当前尝试解析的类型,然后才能对其采取行动,因此如果您需要特定于类型的实现,则必须通过其他方式知道类型 - 和泛型通常(并非总是)对此有所帮助。

【讨论】:

  • 太棒了,有没有什么办法可以在不将 ILogger 转换为泛型类型的情况下做到这一点。我不想这样做,因为我想与 log4net 的 logger impl 保持兼容。
  • 你不需要改变ILogger,但是没有泛型你不能完全做到。查看更新的答案。
  • 如果您尝试使用它,您可能已经注意到它实际上不起作用。这是因为 TinyIoC 在开放泛型方面存在错误:stackoverflow.com/questions/15450518/…
【解决方案2】:

注意:在我的示例中,我使用了ILog,这就是 log4net 所称的特定于类型的记录器类。但它的创建和使用方式似乎与您示例中的 ILogger 完全相同,并且 log4net 的 LogManager.GetLog(Type t) 类似于您的 LoggerFactory.CreateLog(typeofCALLER)

这需要更多的工作,但您可以创建一个通用工厂类来生成特定类型的记录器。将这个工厂类注入构造函数而不是Ilog

TinyIoC 的注册 API 不允许您指定一个知道当前解析类型被注入的包含类型的工厂。以下解决方法有效,因为 TinyIoC 注入了LogFactory&lt;Foo&gt;LogFactory&lt;Bar&gt; 的正确通用实例,然后我们捕获了logFactory.Get() 返回的正确生成的ILog 实例。与我们使用 autofac 相比,需要额外的一些击键——它确实支持你所追求的——但它们不需要太多思考。

假设您想在 FooBar 类中进行一些登录。您只需定义一次LogFactory&lt;T&gt;,并在 Foo、Bar 和任何其他需要使用特定于类型的 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();
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-07
    相关资源
    最近更新 更多