一步一步教你使用Ninject进行依赖注入
首先使用VS新建一个控制台项目TestNinjectConsole,再建立一个类库项目,就叫做Little.Log,打开工具-程序包管理器-程序包管理控制台,输入
install-package ninject
就会自动下载ninject到项目中。
在Little.Log 中新建一个文件夹,叫做ILogs,一个文件夹Logs,项目截图如下
新建一个ILog接口,编码如下
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Little.Log.ILogs { public interface ILog { void WriteLog(string log); } }
然后再建立两个接口,分别为IFileLog,IDataBaseLog,编码如下
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Little.Log.ILogs { public interface IFileLog:ILog { } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Little.Log.ILogs { public interface IDataBaseLog:ILog { } }
然后在Log文件中添加Log类,实现ILog接口
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Little.Log.ILogs; namespace Little.Log.Los { public class Log:ILog { public virtual void WriteLog(string log) { Console.WriteLine(log); } } }
紧接着添加FileLog类和DataBaseLog类,分别实现IFileLog和IDataBaseLog接口,并且都继承于Log类
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Little.Log.ILogs; namespace Little.Log.Los { public class FileLog :Log,IFileLog { private string name = "Filelog:"; public override void WriteLog(string log) { base.WriteLog(name + log); } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Little.Log.ILogs; namespace Little.Log.Los { public class DataBaseLog:Log,IDataBaseLog { private string name = "DataBaseLog:"; public override void WriteLog(string log) { base.WriteLog(name + log); } } }
这样一个基于接口编程的组件就已经准备好了,其实这种模式就传说中Repository模式,有兴趣的话可以查阅相关资料了解这种模式。
下面就是依赖注入的关键部分了。
在控制台项目TestNinjectConsole中新建一个类,叫做MyModule,并且继承于NinjectModule,编码如下
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Ninject.Modules; using Little.Log.ILogs; using Little.Log.Los; namespace TestNinjectConsole { class MyModule :NinjectModule { public override void Load() {
//把接口绑定到具体要实现的类 this.Bind<IFileLog>().To<FileLog>(); this.Bind<IDataBaseLog>().To<DataBaseLog>(); } } }
下面建立一个测试的方法,假设这个方法会记录两种不同的日志,文件日志和数据库日志
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Little.Log.ILogs; namespace TestNinjectConsole { class TestClass { [Ninject.Inject] public IFileLog FileLog { get; set; } [Ninject.Inject] public IDataBaseLog DataBaseLog { get; set; } public void TestFileLog(string log) { FileLog.WriteLog(log); } public void TestDataBaseLog(string log) { DataBaseLog.WriteLog(log); } } }
上面的代码,声明了两种不同接口的属性,但是并没有实例化,并且在属性上方加了[Ninject.Inject]的特性,这是说明这两个属性是通过依赖注入实现的,不需要去手动创建
而且注意这个属性必须声明为公有,不然将会导致注入失败,(也可以使用私有,但是会使用一些特殊配置,此处不做解释)
我们再在Pragram类添加如下代码
private static IKernel kernel; static Program() { kernel = new Ninject.StandardKernel(new MyModule()); } static T GetType<T>() { return kernel.Get<T>(); }
这里是在主函数中注册了内核容器,该容器就是用来做依赖注入的,并且我们在静态构造函数中实例化这个容器,使用我们编写的Module,作为实例化参数。然后又创建了静
态泛型方法,用来获取类的实例,下面我们在主函数中这样使用它
static void Main(string[] args) { var test = GetType<TestClass>(); test.TestFileLog("this is file log."); test.TestDataBaseLog("this is database log."); Console.WriteLine("press any key to continue..."); Console.ReadKey(); }
这样我们就不再需要使用new 方法去创建类了,而是使用GetType<T>()的方法创建类的实例(是不是有点像工厂模式啊...)
而且当我们有很多类的都需要使用到这两个日志记录的类时,难道我们要为每个类都去实例化日志记录类吗?这样的话你的代码可能就是到处都是
FileLog log = new FileLog()这样的代码喽,现在有了依赖注入,是不是会简化好多啊,只要注册一个全局的容器就可以了,而且Ninject不仅支持属性注入,还支持构造
函数注入,接口绑定也是可以带构造参数的哦,再者,我这里其实只是使用一层依赖注入,ninject强大之处可是在于复杂组件的多层次注入哦,详情请参考Ninject API。