c# - 使用 Ninject(或其他一些容器)我如何找出请求服务的类型?

标签 c# .net inversion-of-control structuremap ninject

假设我有一个服务接口(interface):

public interface IFooService
{
   void DoSomething();
}

以及通用服务的具体实现:

public class FooService<TRequestingClass> : IFooService
{
   public virtual void DoSomething() { }
}

我还有其他一些需要 IFooService 实例的类:

public class Bar
{
   private IFooService _fooService;
   public Bar(IFooService fooService)
   {
      this._fooService = fooService;
   }
}

我需要连接我的 IoC 容器,以便在创建 Bar 时向其传递 FooService 的构造函数参数。还有很多其他的类,就像 Bar 一样。每个人可能还需要传递给它们的 FooService 实例,其中 TRequestingClass 是需要 IFooService 实例的类的类型。我不需要向 IFooService 的使用者公开这种古怪之处。他们应该关心的只是他们可以调用传递给他们的 IFooService 的方法。他们不需要知道传递给他们的 IFooService 的具体实现需要构造任何特殊的东西。

FooService 的一个可接受的替代方案是一个非泛型类,它在其构造函数中有一个字符串参数,其中包含为其创建的类的名称。即:

public class FooService : IFooService
{
   public FooService(string requestingClassName) { }
}

如何连接我的 IoC 容器以这种方式构建依赖项?

如果您对为什么我想要这样一个奇怪的结构感到困惑,请考虑当您获得一个使用 log4net.LogManager.GetLogger(typeof(SomeClass)) 创建的 ILog 时,log4net 如何工作得最好。我不想在我的代码中引用 log4net,所以我想编写一个简单的 ILogger 接口(interface),并用类似这样的东西实现它:

public class GenericLogger<T> : ILogger
{
    private readonly ILog log;

    public GenericLogger()
    {
        this.log = log4net.LogManager.GetLogger(typeof(T));
    }

    public void Debug(object message)
    {
        this.log.Debug(message);
    }

    /* .... etc ....  */
}

最佳答案

最简单的方法是创建一个 ILogger<T>接口(interface):

public class ILogger<T> : ILogger { }
public class GenericLogger<T> : ILogger<T> { ... }

然后依靠泛型类型推断得到正确的类型。例如,在 Ninject 中,您只需要以下绑定(bind):

Bind(typeof(ILogger<>)).To(typeof(GenericLogger<>));

那么您的消费类型将如下所示:

public class FooService : IFooService {
  public FooService(ILogger<FooService> logger) { ... }
}

如果您坚决反对 ILogger<T>界面,您可以做一些更有创意的事情,比如自定义提供程序,它读取 IContext确定父类型。

public class GenericLogger : ILogger {
  public class GenericLogger(Type type) { ... }
}

public class LoggerProvider : Provider<ILogger> {
  public override ILogger CreateInstance(IContext context) {
    return new GenericLogger(context.Target.Member.ReflectedType);
  }
}

然后消费类型会像这样工作:

public class FooService : IFooService {
  public FooService(ILogger logger) { ... }
}

关于c# - 使用 Ninject(或其他一些容器)我如何找出请求服务的类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/719346/

相关文章:

C# 编译器优化

使用 Owin 针对 WebApi 的 C# 单元测试项目

c# - WebClient Unicode - 哪个UTF8?

.net - 将可为空的小数点四舍五入到5个小数位

c# - 我需要 Unity 容器的单个实例吗?

c# - 获取实体的属性列表

c# - 上传到 Azure 网站时 SSL 证书不在 X509Store 中

.net - StreamWriter的默认缓冲区大小是多少

.net - 温莎容器 : How to force dispose of an object?

dependency-injection - 原始类型和 IoC 容器