Ninject

Ninject

Ninject之旅之八:Ninject插件模型

摘要: 在前面的章节中,我们看了在单一的绑定条件下Ninject能够处理依赖类型,就是说,每个服务类型只绑定到单一的实现类型。然而,有些情况下我们需要绑定一个抽象服务类型到多个实现,这叫多个绑定。多个绑定有两种情况。第一个是插件模型实现,另一个是上下文绑定。这篇文章介绍插件模型实现,下一篇文章介绍上下文绑定。阅读全文

posted @ 2016-11-16 21:46 丹尼大叔 阅读(121) | 评论 (0) 编辑

Ninject之旅之七:Ninject依赖注入

摘要: 可以使用不同的模式向消费者类注入依赖项,向构造器里注入依赖项是期中一种。有一些遵循的模式用来注册依赖项,同时有一些需要避免的模式,因为他们经常导致不合乎需要的结果。这篇文章讲述那些跟Ninject功能相关的模式和反模式。然而,全面的介绍可以在Mark Seemann的书《Dependency Injection in .NET》中找到。阅读全文

posted @ 2016-11-08 21:52 丹尼大叔 阅读(25) | 评论 (0) 编辑

Ninject之旅之六:Ninject约定

摘要: 在小的应用系统中一个一个注册一些服务类型不怎么困难。但是,如果是一个实际的有上百个服务的应用程序呢?约定配置允许我们使用约定绑定一组服务,而不用一个一个分别绑定。阅读全文

posted @ 2016-11-07 22:03 丹尼大叔 阅读(14) | 评论 (0) 编辑

Ninject之旅之五:Ninject XML配置

摘要: 使用XML配置,需要添加Ninject XML扩展的引用。下一步是添加一个或多个包含类型注册的XML文件。记得这些文件应该跟应用程序一起发布。因此不要忘记将XML文件的属性设置成“Copy if newer”。阅读全文

posted @ 2016-09-28 21:24 丹尼大叔 阅读(21) | 评论 (0) 编辑

Ninject之旅之四:Ninject模块

摘要: 随着应用程序的增长,注册的服务列表跟着变长,管理这个列表将变得困难。Ninject模块是一个好的将我们的类型绑定分离到不同的绑定组的方式,它很容易地将分组组织到不同的文件中。将一个类变成一个Ninject模块只需要将这个类继承INinjectModule接口。每次创建一个Module的时候都需要实现这个接口,需要实现三个方法和两个属性。创建一个抽象类实现这个接口,之后每次创建Ninject模块的时候都继承这个抽象类,这是一个好主意。好消息是Ninject已经有一个这样的抽象类,名称是NinjectModule。阅读全文

posted @ 2016-09-26 20:26 丹尼大叔 阅读(42) | 评论 (0) 编辑

Ninject之旅之三:Ninject对象生命周期

摘要: DI容器的一个责任是管理他创建的对象的生命周期。他应该决定什么时候创建一个给定类型的对象,什么时候使用已经存在的对象。他还需要在对象不需要的时候处理对象。Ninject在不同的情况下管理对象的生命周期提供了强大的支持。在我们定义一个绑定的时候,定义创建对象的范围。在那个范围内,对象将被重用,每次绑定只存在一次。注意,对象不允许依赖于生命周期短自己小的对象。阅读全文

posted @ 2016-08-07 14:20 丹尼大叔 阅读(166) | 评论 (0) 编辑

Ninject之旅之二:开始使用Ninject(附程序下载)

摘要: 这篇文章介绍怎样将Ninject添加到实际的项目中,使用Ninject框架最基本的功能。首先用一个Hello World例子介绍怎么添加和使用Ninject。然后用一个更复杂的例子,介绍Ninject绑定是怎样管理依赖的。阅读全文

posted @ 2016-08-04 21:43 丹尼大叔 阅读(294) | 评论 (0) 编辑

Ninject之旅之一:理解DI

摘要: DI(IoC)是当前软件架构设计中比较时髦的技术。DI(IoC)可以使代码耦合性更低,更容易维护,更容易测试。现在有很多开源的控制反转的框架,Ninject是期中一个轻量级开源的.net DI(IoC)框架。目前已经非常成熟,已经在很多项目中使用。这篇文章讲DI概念以及使用它的优势。使用一个简单的例子,重构这个例子让他逐步符合DI设计原则。阅读全文

posted @ 2016-08-02 14:57 丹尼大叔 阅读(398) | 评论 (4) 编辑

Ninject插件模型

摘要

在前面的章节中,我们看了在单一的绑定条件下Ninject能够处理依赖类型,就是说,每个服务类型只绑定到单一的实现类型。然而,有些情况下我们需要绑定一个抽象服务类型到多个实现,这叫多个绑定。多个绑定有两种情况。第一个是插件模型实现,另一个是上下文绑定。这篇文章介绍插件模型实现,下一篇文章介绍上下文绑定。

插件模型让一个应用程序获得很强的可扩展性而不用修改源代码。下面的例子,我们将实现一个音乐播放器应用程序,使用解码插件来支持不同的音乐格式。这个应用程序使用两个内置的解码器,也可以添加更多的解码器来扩展我们播放器支持的格式。请注意为了让应用程序尽可能简单,许多复杂的细节将不被实现。

先定义一个解码器接口:

1     public interface ICodec
2     {
3         string Name { get; }
4         bool CanDecode(string extension);
5         Stream Decode(Stream inStream);
6     }

添加两个解码器类实现解码器接口:

Mp3:

 1     public class Mp3Codec : ICodec
 2     {
 3         public string Name
 4         {
 5             get
 6             {
 7                 return "MP3 Audio";
 8             }
 9         }
10
11         public bool CanDecode(string extension)
12         {
13             return extension == ".mp3";
14         }
15
16         public Stream Decode(Stream inStream)
17         {
18             //some decode logic added here
19             return null;
20         }
21     }

Wma:

 1 public class WmaCodec : ICodec
 2     {
 3         public string Name
 4         {
 5             get
 6             {
 7                 return "Windows Media Auido";
 8             }
 9         }
10
11         public bool CanDecode(string extension)
12         {
13             return extension == ".wma";
14         }
15
16         public Stream Decode(Stream inStream)
17         {
18             //some decode logic added here
19             return null;
20         }
21     }

下一步是实现我们可插拔的播放器类。让播放器可扩展的是他依赖一系列的ICodec对象,而不是某些具体的解码器:

1 public class Player
2 {
3     private readonly ICodec[] codecs;
4     // Note that the constructor parameter is not a single ICodec.
5     public Player(IEnumerable<ICodec> codecs)
6     {
7         this.codecs = codecs.ToArray();
8     }
9 }

然后添加一个Play方法到播放器类:

1 public void Play(FileInfo fileInfo)
2 {
3     ICodec supportingCodec = FindCodec(fileInfo.Extension);
4     using (var rawStream = fileInfo.OpenRead())
5     {
6         var decodedStream = supportingCodec.Decode(rawStream);
7         PlayStream(decodedStream);
8     }
9 }

这个方法接收一个FileInfo对象,查找合适的解码器后,解码播放这个文件。

实现FindCodec方法:

1 private ICodec FindCodec(string extension)
2 {
3     foreach (ICodec codec in codecs)
4         if (codec.CanDecode(extension))
5             return codec;
6     throw new Exception("File type not supported.");
7 }

FindCodec调用每个codec对象的CanDecode方法来找到支持这个文件扩展名的解码器。如果找不到任何合适的解码器,将抛出一个异常。我们需要记住的一件事是没有具体的解码器在foreach循环之前被解析。

最后在Main方法里添加下面的代码:

1 using (var kernel = new StandardKernel())
2 {
3     kernel.Bind(b => b.FromAssembliesMatching("*")
4         .SelectAllClasses()
5         .InheritedFrom<ICodec>()
6         .BindAllInterfaces());
7 }        

前面的约定指示Ninject自动注册所有的ICodec接口的实现而不是为他们分别每个都声明绑定。

因为ICodec类型被绑定到多个实现,他只能被解析成一系列的对象而不是单一的对象。因此,使用下面的构造函数解析ICodec将导致一个运行时异常:

1 public Consumer(ICodec codec){}

下面的代码也将产生运行时异常:

1 ICodec codec = Kernel.Get<ICodec>();

上面两行代码,Ninject将试着解析ICodec接口,但是它发现多余一个具体的实现类型。代替使用Get<T>,我们可以调用GetAll<T>方法来得到ICodec的所有实现。下面的代码显示所有的支持的codec:

1 IEnumerable<ICodec> codecs = kernel.GetAll<ICodec>();
2 foreach (ICodec codec in codecs)
3 System.Console.WriteLine(codec.Name);

现在,任何的在应用程序的根路径下,有ICodec实现的程序集都将被我们的播放器应用程序认为是一个codec插件。我们的应用程序甚至不需要添加对codec工程的引用。

下面是完整的播放器类代码:

 1 public class Player
 2     {
 3         private readonly ICodec[] _codecs;
 4
 5         // Note that the constructor parameter is not a single ICodec.
 6         public Player(IEnumerable<ICodec> codecs)
 7         {
 8             this._codecs = codecs.ToArray();
 9         }
10
11         public void Play(FileInfo fileInfo)
12         {
13             ICodec supportingCodec = FindCodec(fileInfo.Extension);
14             using (var rawStream = fileInfo.OpenRead())
15             {
16                 var decodedStream = supportingCodec.Decode(rawStream);
17                 PlayStream(decodedStream);
18             }
19         }
20
21         private void PlayStream(Stream decodedStream)
22         {
23             return;
24         }
25
26         private ICodec FindCodec(string extension)
27         {
28             foreach (ICodec codec in _codecs)
29             {
30                 if (codec.CanDecode(extension))
31                 {
32                     return codec;
33                 }
34             }
35             throw new Exception("File type not supported.");
36         }
37     }

时间: 2024-11-04 17:43:36

Ninject的相关文章

Ninject之旅之五:Ninject XML配置

摘要 使用XML配置,需要添加Ninject XML扩展的引用.下一步是添加一个或多个包含类型注册的XML文件.记得这些文件应该跟应用程序一起发布.因此不要忘记将XML文件的属性设置成“Copy if newer”. XML配置文件像下面的配置一样: <module name="moduleName"> <bind service="Namespace.IService1, AssemblyName" to="Namespace.Conc

Ninject之旅之八:Ninject插件模型

摘要 在前面的章节中,我们看了在单一的绑定条件下Ninject能够处理依赖类型,就是说,每个服务类型只绑定到单一的实现类型.然而,有些情况下我们需要绑定一个抽象服务类型到多个实现,这叫多个绑定.多个绑定有两种情况.第一个是插件模型实现,另一个是上下文绑定.这篇文章介绍插件模型实现,下一篇文章介绍上下文绑定. 插件模型让一个应用程序获得很强的可扩展性而不用修改源代码.下面的例子,我们将实现一个音乐播放器应用程序,使用解码插件来支持不同的音乐格式.这个应用程序使用两个内置的解码器,也可以添加更多的解

未能加载文件或程序集 Ninject.Web.Common, Version=3.2.0.0

在Web MVC4中使用NuGet添加NInject.MVC4后,编译报了个警告: 发现同一依赖程序集的不同版本之间存在冲突 然后在运行时就运行到var kernel = new StandardKernel()就报异常: 程序集清单定义与程序集引用不匹配 无法运行,经检查运行时程序清单是Ninject.Web.Common3.2,但项目安装的却是Ninject.Web.Common3.0. 解决方法:用NuGet先安装Ninject.Web.Common,再安装NInject.MVC4,即解决

使用Ninject+Moq在单元测试中抽象数据访问层

一.测试方法的业务逻辑时,通常都需要从数据库读取测试数据,但是每次初始化数据库数据都很麻烦,也会影响到其它业务对数据的访问,怎样抽象数据访问层呢?就是用Moq去模拟数据访问的逻辑 二.步骤如下 2.1 定义数据访问接口和实现 public interface IDBAccess { List<string> GetList(string request); } public class DBAccessImp : IDBAccess { public List<string> Ge

ASP.NET MVC学前篇之Ninject的初步了解

1.介绍 废话几句,Ninject是一种轻量级的.基础.NET的一个开源IoC框架,在对于MVC框架的学习中会用到IoC框架的,因为这种IoC开源框架有很多,本篇的主题只有一个,就是让阅读过本篇幅的朋友逗知道IoC框架在项目中的作用,以及它的重要性. 这样做的目的是以便在以后的学习工作中选择自己中意的一个IoC框架来学习.使用,或者是自己去实现一个.好了,不废话了. 2.环境准备 1.新建个4.0Framework的一个控制台应用程序项目,名称为IoCDemo 2.在http://www.nin

Ninject之旅之十三:Ninject在ASP.NET MVC程序上的应用

摘要: 在Windows客户端程序(WPF和Windows Forms)中使用Ninject和在控制台应用程序中使用Ninject没什么不同.在这些应用程序里我们不需要某些配置用来安装Ninject,因为在Windows客户端应用程序里,开发者可以控制UI组件的实例化(Forms或Windows),可以很容易地委托这种控制到Ninject.然而在Web应用程序里,就不同了,因为框架负责了实例化UI元素.因此,我们需要知道怎样告诉框架委托这种控制责任给Ninject.幸运的是,让ASP.NET M

Ninject之旅之十一:Ninject动态工厂(附程序下载)

摘要 如果我们已经知道了一个类所有的依赖项,在我们只需要依赖项的一个实例的场景中,在类的构造函数中引入一系列的依赖项是容易的.但是有些情况,我们需要在一个类里创建依赖项的多个实例,这时候Ninject注入就不够用了.也有些情况,我们不知道一个消费者可能需要哪个服务,因为他可能在不同的场合下需要不同的服务,而且在创建类的时候实例化所有依赖项也不合理.这样的情况,动态工厂可以帮忙.我们可以设计我们的类让他依赖一个工厂,而不是依赖这个工厂能够创建的对象.然后,我们能够命令工厂去通过命令创建需要的类型和

Ninject之旅之七:Ninject依赖注入

摘要 可以使用不同的模式向消费者类注入依赖项,向构造器里注入依赖项是期中一种.有一些遵循的模式用来注册依赖项,同时有一些需要避免的模式,因为他们经常导致不合乎需要的结果.这篇文章讲述那些跟Ninject功能相关的模式和反模式.然而,全面的介绍可以在Mark Seemann的书<Dependency Injection in .NET>中找到. 1.构造函数注入 构造函数时推荐的最常用的向一个类注册依赖项的模式.一般来说,这种模式应该经常被用作主要的注册模式,除非我们不得不使用其他的模式.在这个

使用Ninject进行DI(依赖注入)

Ninject是一个快如闪电.超轻量级的基于.Net平台的依赖注入框架.它能够帮助你把应用程序分离成一个个松耦合.高内聚的模块,然后用一种灵活的方式组装起来.通过使用Ninject配套你的软件架构,那么代码将会变得更加容易编写.重用性强.易于测试和修改.下面是一个简单的调用示例: 定义接口与基础类 interface IDocumentDAL { string Save(Document Entity); } public class Document { public int Id { get

使用 Ninject

在[ASP.NET MVC 小牛之路]系列上一篇文章(依赖注入(DI)和Ninject)的末尾提到了在ASP.NET MVC中使用Ninject要做的两件事情,续这篇文章之后,本文将用一个实际的示例来演示Ninject在ASP.NET MVC中的应用. 为了更好的理解和撑握本文内容,强烈建议初学者阅读本文前先阅读依赖注入(DI)和Ninject. 本文目录: 准备工作 新建一个名为BookShop的空白解决方案.在该解决方案中分别添加一个名为BookShop.WebUI的MVC空应用程序,和一个