Ninject 依赖注入
依赖性解析器用于避免紧密耦合的类,提高灵活性并使测试变得容易。你可以创建自己的依赖注入器(不推荐)或使用编写良好且经过测试的依赖注入器之一。在这个例子中,我将使用 Ninject 。
第一步:创建依赖解析器
首先,从 NuGet 下载 Ninject 。创建名为 Infrastructure 的文件夹并添加名为 NinjectDependencyResolver 的类 :
using Ninject;
using System;
using System.Collections.Generic;
using System.Web.Mvc;
public class NinjectDependencyResolver
: IDependencyResolver
{
private IKernel kernel;
public NinjectDependencyResolver()
{
// Initialize kernel and add bindings
kernel = new StandardKernel();
AddBindings();
}
public object GetService(Type serviceType)
{
return kernel.TryGet(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
return kernel.GetAll(serviceType);
}
private void AddBindings()
{
// Bindings added here
}
}
当 MVC 框架需要一个类的 insance 来为传入的请求提供服务时,它将调用 GetService 和 GetServices 方法。
第二步:注册依赖解析器
现在我们有自定义依赖项解析器,我们需要注册它以告诉 MVC 框架使用我们的依赖项解析器。在 Global.asax.cs 文件中注册依赖项解析器 :
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
DependencyResolver.SetResolver(new NinjectDependencyResolver());
// .....
}
第三步:添加绑定
想象一下,我们有以下接口和实现:
public interface ICustomCache
{
string Info { get; }
}
public class CustomCache : ICustomCache
{
public string Info
{
get
{
return "Hello from CustomCache.";
}
}
}
如果我们想在我们的控制器中使用 CustomCache 而不将我们的控制器与 CustomCache 紧密耦合,那么我们需要将 ICustomCache 绑定到 CustomCache 并使用 Ninject 注入它。第一件事首先,结合 ICustomCache 到 CustomCache 通过添加以下代码来 AddBindings()
的方法 NinjectDependencyResolver :
private void AddBindings()
{
// Bindings added here
kernel.Bind<ICustomCache>().To<CustomCache>();
}
然后准备你的注射控制器,如下所示:
public class HomeController : Controller
{
private ICustomCache CustomCache { get; set; }
public HomeController(ICustomCache customCacheParam)
{
if (customCacheParam == null)
throw new ArgumentNullException(nameof(customCacheParam));
CustomCache = customCacheParam;
}
public ActionResult Index()
{
// cacheInfo: "Hello from CustomCache."
string cacheInfo = CustomCache.Info;
return View();
}
}
这是构造函数注入的示例,它是依赖注入的一种形式。如你所见,我们的 Home 控制器不依赖于 CustomCache 类 itslef。如果我们想在我们的应用程序中使用另一个 ICustomCache,我们唯一需要改变的是将 ICustomCache 绑定到另一个实现,这是我们需要采取的唯一步骤。这里发生的事情是,MVC 框架要求我们注册的依赖项解析器通过 GetService 方法创建 HomeController 类的实例。GetService 方法请求 Ninject 内核创建请求的对象,Ninject 内核检查其术语中的类型,并发现 HomeController 的构造函数重新获取 ** ICustomCache 并结合已添加 ICustomCache 。Ninject 创建绑定类的实例,使用它创建 HomeController 并返回它 MVC Framework。
依赖链
当 Ninject 尝试创建类型时,它会检查类型和其他类型之间的其他依赖关系,如果有任何 Ninject 也尝试创建它们。例如,如果我们的 CustomCache 类需要 ICacheKeyProvider,并且如果为 ICacheKeyProvider 添加了 bining,Ninject 可以为我们的类提供它。
ICacheKeyProvider 接口和 SimpleCacheKeyProvider 实现:
public interface ICacheKeyProvider
{
string GenerateKey(Type type);
}
public class SimpleCacheKeyProvider
: ICacheKeyProvider
{
public string GenerateKey(Type type)
{
if (type == null)
throw new ArgumentNullException(nameof(type));
return string.Format("{0}CacheKey", type.Name);
}
}
修改了 CustomCache 类
public class CustomCache : ICustomCache
{
private ICacheKeyProvider CacheKeyProvider { get; set; }
public CustomCache(ICacheKeyProvider keyProviderParam)
{
if (keyProviderParam == null)
throw new ArgumentNullException(nameof(keyProviderParam));
CacheKeyProvider = keyProviderParam;
}
...........
}
为 ICacheKeyProvider 添加绑定 :
private void AddBindings()
{
// Bindings added here
kernel.Bind<ICustomCache>().To<CustomCache>();
kernel.Bind<ICacheKeyProvider>().To<SimpleCacheKeyProvider>();
}
现在,当我们导航到 HomeController 时, Ninject 会创建 SimpleCacheKeyProvider 的实例,使用它来创建 CustomCache 并使用 CustomCache 实例来创建 HomeController 。
Ninject 有很多很棒的功能,如链接依赖注入,如果你想使用 Ninject,你应该检查它们。