轻量级IOC框架:Ninject

时间:2023-03-08 22:09:57
轻量级IOC框架:Ninject

Ninject 学习杂记 - liucy

IOC容器的DI实现并不依赖于方法调用拦截,而是通过DI容器内部自己通过反射的方式生成需要的类型实例,并调用实例的成员。然后再把实例返回给容器外部环境使用。 
Ninject本身及其扩展库,还针对特定的开发平台或项目类型提供了专用的DI支持,比如针对WPF/SL,针对ASP.NET MVC 
Ninject 的扩展库 也是基于Ninject核心库的,对于某些特定场景的功能补充 
StandardKernel 是Ninject中的IOC容器类,Get方法是显式的得到某类型的实例, Bind方法是类型映射注册,注册以后,Ninject就可以根据程序的需要来提供实例创建。 
using (var kernel = new Ninject.StandardKernel()) 

var service = kernel.Get<SalutationService>(); 
kernel.Bind<ILog>().To<ConsoleLog>(); 
service.SayHello(); 

如果没有特别指定由Ninject创建的类型实例的生命周期,那么就是默认的每次都由Ninject提供一个新的类型实例,Ninject不负责管理它的lifecycle 
Kernel.Bind<Ilogger>().To<ConsoleLogger>().InSingletonScope(); 来显式的指定实例是以单例形式存在,每次Ninject都只提供已经存在的类型实例,而不是重新构建新的。 
.InThreadScope() 对同一线程提供同一实例 
.InRequestScope() 针对同一Web request 提供同一实例。 
.InScope(func) 可以由开发者自己定义Scope, 直到func 返回的值发生了变化,才重新构建新的实例。 
Kernel.Bind<MailService>().ToSelf() 是把某类型自己映射到自己。 
Ninject Module: Module 是作为Ninject中对 类型绑定映射进行分组管理的单元。 
public class LoggerModule : NinjectModule 

public override void Load() 

Bind<ILog>().To<ConsoleLog>().InSingletonScope(); 


static void Main(string[] args) 

using (var kernel = new Ninject.StandardKernel(new LoggerModule())) 

var logger = kernel.Get<ILog>(); 
logger.Log("wow"); 


We can also load all of the Ninject modules defned in an application at the same 
time using the following code: 
kernel.Load(AppDomain.CurrentDomain.GetAssemblies()); 
Ninject 还允许通过XML配置文件形式来定义类型绑定映射, 之后就可以通过Kernel.Load("Config.xml") 的形式读取配置信息,并完成映射注册

Ninject通过NinjectModule来配置依赖注入(不知道有没有文件配置,在官方教程里没找到相关资料),这里自定义自己的Module:

internal class MyModule : Ninject.Modules.NinjectModule 
{ 
  public override void Load() 
  { 
    Bind<ILogger>().To<FlatFileLogger>(); 
    Bind<ILogger>().To<DatabaseLogger>(); 
  } 
}

  具体调用方法:

private static IKernel kernel = new StandardKernel(new MyModule()); 
static void Main(string[] args) 
{ 
  ILogger logger = kernel.Get<ILogger>(); 
  logger.Write("Bruce Say: Hello Ninject!"); 
  Console.WriteLine("continues.."); 
  Console.Read(); 
}

  通过 kernel.Get<ILogger>() 来获取ILogger的实例,之前在MyModule里先后对ILogger 绑定了FlatFileLogger 和 DatabaseLogger,而kernel.Get<ILogger>() 这里返回第一个绑定的对象,即FlatFileLogger。

  构造函数注入

  这里新建一个ITester 和 IocTester, 而IocTester 依赖于ILogger:

interface ITester 
{ 
  void Test(); 
} 
class IocTester:ITester 
{ 
  private ILogger _logger; 
  public IocTester(ILogger logger) 
  { 
    _logger = logger; 
  } 
  public void Test() 
  { 
    _logger.Write("Bruce Say: Hello Ninject!"); 
  } 
}

  下面看看Ninject是怎么配置的,很简单修改MyModule,绑定ITester:Bind<ITester>().To<IocTester>():

internal class MyModule : Ninject.Modules.NinjectModule 
{ 
  public override void Load() 
  { 
    Bind<ILogger>().To<FlatFileLogger>(); 
    Bind<ITester>().To<IocTester>(); 
  } 
}

  从以上配置中,我们是看不到IocTester 和ILogger 是有依赖关系的,这就是依赖注入的好处。只是简单告诉哪个接口对应哪个类,剩下的任务就可以交给Ninject来处理了。

private static IKernel kernel = new StandardKernel(new MyModule()); 
static void Main(string[] args) 
{ 
  ITester tester = kernel.Get<ITester>(); 
  tester.Test(); 
  Console.WriteLine("continues.."); 
  Console.Read(); 
}

原创文字只代表本人某一时间内的观点或结论,本人不对涉及到的任何代码担保。转载请标明出处!