依赖注入容器-- Autofac
Posted hulizhong
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了依赖注入容器-- Autofac相关的知识,希望对你有一定的参考价值。
目录:
一、简介
二、如何使用
2.1、基本使用
2.2、接口使用
2.3、 其他注入
2.4、 注入的生命周期
一、简介
在上一篇文章中讲到替换默认服务容器,我们选择了Autofac
Autofac---Autofac是一款IOC框架,比较于其他的IOC框架,如Spring.NET,Unity,Castle等等所包含的,它很轻量级性能上非常高。
我们在.Net Core 中替换了自带的默认服务容器,选择采用Autofac,那么如何去使用它呢?
二、如何使用
TestController控制器
public class TestController : Controller { private static Animals _animals; public IActionResult Index() { ViewBag.Animal = _animals.Cry(); return View(); } }
替换修改后的Startup.cs 中的ConfigureServices
public IServiceProvider ConfigureServices (IServiceCollection services) { services.AddMvc(); // Add other framework services // Add Autofac var containerBuilder = new ContainerBuilder(); containerBuilder.Populate(services); var container = containerBuilder.Build(); return new AutofacServiceProvider(container); }
1.1、 基本使用
创建 Animals 类
public class Animals { public string Cry() { return "小狗,汪汪汪"; } }
ConfigureServices 中添加注册
containerBuilder.RegisterType<Animals>();
TestController 控制器中添加构造函数
public TestController(Animals animals) { _animals = animals; }
运行起来看下
1.2、 接口使用
创建IAnimals.cs
public interface IAnimals { string Cry(); } public class DogCry : IAnimals { public string Cry() { return "小狗,汪汪汪"; } } public class CatCry : IAnimals { public string Cry() { return "小猫,喵喵喵"; } }
ConfigureServices 中添加注册
containerBuilder.RegisterType<DogCry>().As<IAnimals>();
TestController 控制器中添加构造函数并修改_animals为对应的类型
public TestController(IAnimals animals) { _animals = animals; }
运行起来
如果一个类型被多次注册,以最后一个注册的为准
ConfigureServices 中添加注册
containerBuilder.RegisterType<DogCry>().As<IAnimals>();
containerBuilder.RegisterType<CatCry>().As<IAnimals>();
运行起来看下
1.3、 其他注入
1、 自动装配—从容器里面选择一个构造方法来创建对象
创建Cry类
public class Cry { public Cry() { voice= "小狗,汪汪汪"; } public Cry(string voices) { if (string.IsNullOrWhiteSpace(voices)) { voice = "旺旺旺"; } voice= $"小狗,{voices}"; } public Cry(string name, string voices):this(voices) { if (string.IsNullOrWhiteSpace(voices)) { voice = "旺旺旺"; } if (string.IsNullOrWhiteSpace(name)) { voice = "柴犬"; } voice= $"{name},{voices}"; } public static string voice { get; set; } }
ConfigureServices 中添加注册
containerBuilder.RegisterType<Cry>().UsingConstructor(typeof(string));
Autofac会默认从容器中选择参数最多的构造函数,如果想要指定选择的话可以指定UsingConstructor
2、 实例化注入
还是上面的Cry类
ConfigureServices 中添加注册
var output = new Cry("叫声叫声"); containerBuilder.RegisterInstance(output).ExternallyOwned();
先对对象实例化然后注册,ExternallyOwned--配置组件,使容器永远不会处理实例。
修改Test控制器
public IActionResult Index() { ViewBag.Animal = Cry.voice; return View(); }
1.4、 注入的生命周期
1、 Transient(暂时生存期)--暂时生存期服务是每次从服务容器进行请求时创建的。 这种生存期适合轻量级、 无状态的服务。
2、 Scoped(范围生存期)--范围生存期服务是每个客户端请求连接时创建的一次实例
3、 Singleton(单例生存期)--单例生存期会在程序第一次请求是创建一次实例,不会变化的
我们来利用生成guid来看一下三个的生命周期有什么具体的不一样
修改Test控制器
public class TestController : Controller { private static IGetTransient _getTransient; private static IGetScoped _getScoped; private static IGetSingleton _getSingleton; public TestController(IGetTransient getTransient, IGetScoped getScoped, IGetSingleton getSingleton) { _getTransient = getTransient; _getScoped = getScoped; _getSingleton = getSingleton; } public IActionResult Index() { ViewBag.getTransient = _getTransient.GuidItem(); ViewBag.getScoped = _getScoped.GuidItem(); ViewBag.getSingleton = _getSingleton.GuidItem(); return View(); } }
修改Index.cshtml
<div> <span>Transient:</span><span>@ViewBag.getTransient</span> </div> <div> <span>Scoped:</span><span>@ViewBag.getScoped</span> </div> <div> <span>Singleton:</span><span>@ViewBag.getSingleton</span> </div>
IGuid接口
public interface IGuid { Guid GuidItem(); } /// <summary> /// 暂存生存期 /// </summary> public interface IGetTransient : IGuid { } /// <summary> /// 范围生存期 /// </summary> public interface IGetScoped : IGuid { } /// <summary> /// 单例生存期 /// </summary> public interface IGetSingleton : IGuid { }
GuidServiceBase类
public class GuidServiceBase: IGuid { private readonly Guid _item; public GuidServiceBase() { _item = Guid.NewGuid(); } public Guid GuidItem() { return _item; } } /// <summary> /// 暂存生存期 /// </summary> public class GuidTransientService : GuidServiceBase, IGetTransient { } /// <summary> /// 范围生存期 /// </summary> public class GuidScopedService : GuidServiceBase, IGetScoped { } /// <summary> /// 单例生存期 /// </summary> public class GuidSingletonService : GuidServiceBase, IGetSingleton { }
ConfigureServices 中添加注册
containerBuilder.RegisterType<GuidTransientService>().As<IGetTransient>(); containerBuilder.RegisterType<GuidScopedService>().As<IGetScoped>().InstancePerLifetimeScope();
containerBuilder.RegisterType<GuidSingletonService>().As<IGetSingleton>().SingleInstance();
运行起来发现Singleton(单例生存期)没有变化,仅产生了一个实例,但是Scoped(范围生存期) 变化的不一样,按照理论来说应该刷新之后会变化,但是两边应该会是一样的值。--(因为两个页面依然是独立的,并不是一次请求)。我们换另一种方式验证这个
修改Test控制器—新增Guid
public IActionResult Guid() { return View(); }
添加Guid.cshtml—通过inject注入依赖
@{ Layout = null; } @inject WebApplication3.IGetTransient TransientService @inject WebApplication3.IGetScoped GuidScopedService @inject WebApplication3.IGetSingleton GuidSingletonService
<!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>Guid</title> </head> <body> <div class="row"> <div> <h2>GuidItem Shows</h2> <h3>TransientItem: @TransientService.GuidItem()</h3> <h3>ScopedItem: @GuidScopedService.GuidItem()</h3> <h3>SingletonItem: @GuidSingletonService.GuidItem()</h3> </div> </div> </body> </html>
修改Index.cshtml
@{ ViewData["Title"] = "Index"; } <h1>Index</h1> @Html.Partial("Guid") <h1>Guid</h1> @Html.Partial("Guid")
运行然后打开两个页面
我们再次完全吻合的,暂时生命周期在每次使用的时候的Guid(实例)都是变化的,范围生命周期在同一个请求范围内Guid是不变化的,不同请求的Guid是会发生变化的。但是单例生命周期的Guid从程序开始就不会发生变化的。
以上是关于依赖注入容器-- Autofac的主要内容,如果未能解决你的问题,请参考以下文章