使用Ninject(或其他容器),我怎么能找出被请求服务的类型? [英] Using Ninject (or some other container) How can I find out the type that is requesting the service?

查看:111
本文介绍了使用Ninject(或其他容器),我怎么能找出被请求服务的类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个服务的接口:

 公共接口IFooService 
{
无效DoSomething的();
}

和具体实现该服务的是一个通用的:

 公共类FooService接口< TRequ​​estingClass> :IFooService 
{
公共虚拟无效的doSomething(){}
}

和我有需要IFooService的一个实例,其他类:

 公共类酒吧
{
私人IFooService _fooService;
公开栏(IFooService FooService接口)
{
this._fooService = FooService接口;
}
}



我需要接线了我的IoC容器,这样当酒吧被创建,它被传递FooService接口℃的构造函数参数;酒吧取代。还有许多其他类一样吧。每个可能还需要FooService接口和LT的实例; TRequ​​estingClass>传递给它们,其中TRequ​​estingClass是需要IFooService的实例的类的类型。我不需要这个诡异暴露在消费者IFooService的。他们所应该关心的是,他们可以打电话,他们通过IFooService的方法。他们不应该需要知道IFooService的具体实现,他们需要通过什么特别的构造



这是可以接受的alternatative到FooService接口< T>将向是在其constructur一个字符串参数包含它正在为创建的类名非通用类。即:

 公共类FooService接口:IFooService 
{
公共FooService接口(字符串requestingClassName){}
}

我怎样才能线了我的IoC容器构建依赖这种方式?



如果你是困惑,为什么我会想这样一个奇怪的结构,可以考虑当你得到的是它和log4net.LogManager创建的ILog log4net的是如何工作的最好的。 GetLogger(typeof运算(SomeClass的))。我不想我的垃圾用引用代码log4net的,所以我想编写一个简单的ILogger接口,像这样实现:

 公共类GenericLogger< T> :ILogger 
{
私人只读的ILog日志;

公共GenericLogger()
{
this.log = log4net.LogManager.GetLogger(typeof运算(T));
}

公共无效调试(对象消息)
{
this.log.Debug(消息);
}

/ * ....等.... * /
}


解决方案

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

 公共类ILogger< T> :ILogger {} 
公共类GenericLogger< T> :ILogger< T> {...}



然后依靠通用的类型推断,以获得正确的类型。例如,在Ninject,下面结合是所有你需要:

 绑定(typeof运算(ILogger<>)) 。要(typeof运算(GenericLogger<>)); 



那么你的消费类型是这样的:

 公共类FooService接口:IFooService {
公共FooService接口(ILogger< FooService接口>记录器){...}
}

如果你是坚决反对的 ILogger< T> 界面,你可以做什么更有创意,比如自定义提供,其内容的 IContext 来确定父类型。

 公共类GenericLogger:ILogger {
公共类GenericLogger(类型类型){...}
}

公共类LoggerProvider:供应商< ILogger> {
公众覆盖ILogger的CreateInstance(IContext上下文){
返回新GenericLogger(context.Target.Member.ReflectedType);
}
}



然后消费类型将工作是这样的:

 公共类FooService接口:IFooService {
公共FooService接口(ILogger记录仪){...}
}


Suppose I have an interface for a service:

public interface IFooService
{
   void DoSomething();
}

And a concrete implementation of that service that is a generic:

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

And I have some other class that needs an instance of IFooService:

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

I need to wire up my IoC container such that when Bar gets created, it gets passed a constructor argument of FooService<Bar>. There are many other classes just like Bar. Each might also need an instance of FooService<TRequestingClass> passed to them where TRequestingClass is the type of the class that needs the instance of IFooService. I don't need to expose this quirkiness to the consumers of IFooService. All they should care about is that they can call the methods of the IFooService they were passed. They should not need to know that the concrete implementation of IFooService they were passed needed anything special to be constructed.

An acceptable alternatative to FooService<T> would to be a non-generic class that has a string argument in its constructur that contains the name of the class it is being created for. i.e:

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

How can I wire up my IoC container to construct a dependency this way?

If you are confused why I would want such a wierd structure, consider how log4net works best when you get an ILog that gets created with log4net.LogManager.GetLogger(typeof(SomeClass)). I don't want to litter my code with references to log4net, so I'd like to write a simple ILogger interface, and implement it with something like this:

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 ....  */
}

解决方案

The easiest way would be to create an ILogger<T> interface:

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

Then rely on generic type inference to get the correct type. For example, in Ninject, the following binding is all you'd need:

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

Then your consuming types would look like this:

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

If you're adamantly against the ILogger<T> interface, you could do something more creative, like a custom provider, which reads the IContext to determine the parent type.

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);
  }
}

Then consuming types would work like this:

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

这篇关于使用Ninject(或其他容器),我怎么能找出被请求服务的类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆