1.参考资料:
①.http://www.jessetalk.cn/2017/11/06/di-in-aspnetcore/
②.https://www.cnblogs.com/GuZhenYin/p/8297145.html
③.https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-3.0
④.https://www.cnblogs.com/yilezhu/p/9998021.html
⑤.https://www.cnblogs.com/Erhao/p/11118642.html
2.依赖注入(DependencyInjection:DI):意思自身对象中的内置对象是通过注入的方式进行创建。形象的说,即由容器动态的将某个依赖关系注入到组件之中。
①.依赖?谁依赖谁?
结果:当一个类需要另一个类协作来完成工作就产生了依赖。就如腾飞博客介绍的那样,对哒,就是酱紫(http://www.jessetalk.cn/2017/11/06/di-in-aspnetcore/)
②.注入?谁注入谁?
结果:将所依赖的对象进行注入,包括所注入对象的所有资源(对象、资源、数据)???接口与实现??{好像还是不太对-.-.......};注入更能体现的是IOC思想
③.控制反转IOC(Inversion of Control)?
结果:控制反转其实是一种思想,并非一种技术,就如DI一样,也只是一种设计思想,在不使用ioc设计下,我们创建对象一般都是使用new来创建一个对象;使用ioc后,创建对象的控制器有内部转到外部,接收外部传递进来的对象(依赖对象?),
1.正转:就如鹏飞的文章中,
2.反转?:为了在业务变化的时候尽量减少改动代码造成的问题(大多数文章都是酱紫理解的,感觉也很符合实际需求)
④.容器?core中自带的IOC容器(NET Core MVC中的Startup.cs)
结果:用来管理依赖注入实例的坛子(感觉没毛病...);容器主要负责两件事:1.绑定服务于实例之间的关系(依赖?)2.获取实例,并对实例进行管理(创建与销毁)
⑤.实例生命周期?Transent/Scoped/Singleton(单例)
1.Transent:每次请求时都会创建,并且永远不会被共享。
2.Scoped:在同一个Scope内只初始化一个实例 ,可以理解为( 每一个request级别只创建一个实例,同一个http request会在一个 scope内)
3.Singleton:整个应用程序生命周期内只会创建一个实例。该实例在需要它的所有组件之间共享。因此总是使用相同的实例。
⑥.使用DI的好处?
结果:1.减少程序之间的松散耦合,减少依赖(?),有利于功能复用 2.使程序结构清晰,利于测试
⑦.常见的IOC框架:
1.DependencyInjection(微软自带DI)
2.Autofac
3.Unity
⑧.注册服务的方式:
ITestService.cs接口:
public interface ITestService { List<string> GetList(string a); }
TestService.cs接口实现:
public class TestService : ITestService { public List<string> GetList(string a) { return new List<string>() { "张三", "李四", "王五" }; } }
1.推荐的一种使用方式:
public void ConfigureServices(IServiceCollection services) { services.Configure<CookiePolicyOptions>(options => { // This lambda determines whether user consent for non-essential cookies is needed for a given request. options.CheckConsentNeeded = context => true; options.MinimumSameSitePolicy = SameSiteMode.None; }); services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); // 注入服务 services.AddTransient<ITestService, TestService>(); services.AddDirectoryBrowser(); }
2.另外的方式:
public void ConfigureServices(IServiceCollection services) { services.Configure<CookiePolicyOptions>(options => { // This lambda determines whether user consent for non-essential cookies is needed for a given request. options.CheckConsentNeeded = context => true; options.MinimumSameSitePolicy = SameSiteMode.None; }); services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); // 注入服务 //services.AddTransient<ITestService, TestService>(); //services.AddDirectoryBrowser(); //注入服务 services.Add(new ServiceDescriptor(typeof(ITestService), typeof(TestService), ServiceLifetime.Transient)); }
3.Action注入的方法:使用[FromServices]
public class HomeController : Controller {
private readonly ITestService _testService;
//此处为构造函数注入方式 public HomeController(ITestService testService) { _testService = testService; } //这里采用推荐的依赖注入方式 public IActionResult Index() { ViewBag.date = _testService.GetList(""); return View(); } //这里采用Action注入的方式 public IActionResult Privacy([FromServices] ITestService testService1) { ViewBag.date = testService1.GetList(""); return View(); }
3.Example
①.实例生命周期实例:
-(1).新建一个ASP.NET Core Web应用程序.
-(2).新建三个接口,三个接口实现类
ITestServiceTransient.cs
/// <summary> /// Transient:瞬时的 /// </summary> public interface ITestServiceTransient { Guid TrGudi { get; } List<string> GetList(string a); }
ITestServiceScoped.cs
/// <summary> /// Scoped:作用域的 /// </summary> public interface ITestServiceScoped { Guid ScoGuid { get; } List<string> GetList(); }
ITestServiceSingleton.cs
/// <summary> /// Singleton:唯一的 /// </summary> public interface ITestServiceSingleton { Guid SingGuid { get; } List<string> GetList(); }
TestServiceTransient.cs
public class TestServiceTransient : ITestServiceTransient { public TestServiceTransient() { TrGudi = Guid.NewGuid(); } public Guid TrGudi { get; set; } public List<string> GetList(string a) { return new List<string>() { "AA", "BB", "CC" }; } }
TestServiceScoped.cs
public class TestServiceScoped : ITestServiceScoped { public TestServiceScoped() { ScoGuid = Guid.NewGuid(); } public Guid ScoGuid { get; set; } public List<string> GetList() { return new List<string>() { "A", "B", "C" }; } }
TestServiceSingleton.cs
public class TestServiceSingleton : ITestServiceSingleton { public TestServiceSingleton() { SingGuid = Guid.NewGuid(); } public Guid SingGuid { get; set; } public List<string> GetList() { return new List<string>() { "a", "b", "c" }; } }
-(3).注入服务:Startup.cs
public void ConfigureServices(IServiceCollection services) { services.Configure<CookiePolicyOptions>(options => { // This lambda determines whether user consent for non-essential cookies is needed for a given request. options.CheckConsentNeeded = context => true; options.MinimumSameSitePolicy = SameSiteMode.None; }); services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); // 注入服务 services.AddTransient<ITestServiceTransient, TestServiceTransient>(); services.AddSingleton<ITestServiceSingleton, TestServiceSingleton>(); services.AddScoped<ITestServiceScoped, TestServiceScoped>(); services.AddDirectoryBrowser(); }
-(4).修改Home下的控制器跟视图
HomeControlle.cs
public class HomeController : Controller { private readonly ITestServiceTransient _testServiceTransient; private readonly ITestServiceSingleton _testServiceSingleton; private readonly ITestServiceScoped _testServiceScoped; // 构造函数注入 public HomeController(ITestServiceTransient testServiceTransient, ITestServiceSingleton testServiceSingleton, ITestServiceScoped testServiceScoped) { _testServiceTransient = testServiceTransient; _testServiceSingleton = testServiceSingleton; _testServiceScoped = testServiceScoped; } //这里采用推荐的注入方式 public IActionResult Index() { ViewBag.date = _testServiceTransient.GetList(""); ViewBag.guidTr = _testServiceTransient.TrGudi; ViewBag.guidSco = _testServiceScoped.ScoGuid; ViewBag.guidSing = _testServiceSingleton.SingGuid; return View(); } //这里采用Action注入的方式 public IActionResult Privacy([FromServices] ITestServiceTransient testServiceTransient,[FromServices] ITestServiceScoped testServiceScoped,[FromServices] ITestServiceSingleton testServiceSingleton ) { ViewBag.date = testServiceTransient.GetList(""); ViewBag.guidTr = testServiceTransient.TrGudi; ViewBag.guidTr1 = _testServiceTransient.TrGudi;// ?? 这个对象是来至于构造函数的?? ViewBag.guidSco = testServiceScoped.ScoGuid; ViewBag.guidSco1 = _testServiceScoped.ScoGuid; ViewBag.guidSing = testServiceSingleton.SingGuid; ViewBag.guidSing1 = _testServiceSingleton.SingGuid; return View(); } [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] public IActionResult Error() { return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier }); } }
Index.cshtml
@{ ViewData["Title"] = "Home Page"; } <div class="text-center"> <h1 class="display-4">Welcome</h1> <p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p> @foreach (var item in ViewBag.date) { <h5>@item</h5> } </div> <h2>瞬时的:@ViewBag.guidTr</h2> <h2>瞬时的:@ViewBag.guidTr</h2> <h2>作用域的:@ViewBag.guidSco</h2> <h2>作用域的:@ViewBag.guidSco</h2> <h2>唯一的:@ViewBag.guidSing</h2> <h2>唯一的:@ViewBag.guidSing</h2>
Privacy.cshtml
@{ ViewData["Title"] = "Privacy Policy"; } <h1>@ViewData["Title"]</h1> <p>Use this page to detail your site's privacy policy.</p> @foreach (var item in ViewBag.date) { <h5>@item</h5> } <h2>瞬时的:@ViewBag.guidTr</h2> <h2>瞬时的:@ViewBag.guidTr1</h2> <h2>作用域的:@ViewBag.guidSco</h2> <h2>作用域的:@ViewBag.guidSco1</h2> <h2>唯一的:@ViewBag.guidSing</h2> <h2>唯一的:@ViewBag.guidSing1</h2>
-(5).输出:来回点击Home与Privacy进行切换访问,观察3个属性周期的变化
Home:
Privacy:
-(6).多次点击Home或者Privacy页面进行访问,发现以下结论:
--1.Home与Privacy页面的唯一属性Singleton是一样,说明在同一个程序的生命周期内,Singleton值是唯一的(全局只创建一次,第一次被请求的时候被创建,然后就一直使用这一个)
--2.Home与Privacy页面的作用域值Scoped是随着改变的,并且两个视图页面的值不一样,说明两个视图作为两个单独的对象来进行访问( 在同作用域,服务每个请求只创建一次)
--3.Home的瞬时值Transient在每次访问都会重新进行创建(这个生命周期最适合轻量级,无状态的服务),Privacy中的两个Transient值每次访问都不相同(?),是否是因为Privacy视图中的“ViewBag.guidTr1 = _testServiceTransient.TrGudi;”来至于构造函数?(每次请求时都会创建的瞬时生命周期服务)