C#.NET CORE的AddScoped之容器注入对象和接口实现的区别
一,代码结构如下
二,我们线直接上代码,如下:
using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using CoreIocTest.Models; using CoreIocTest.Interface; namespace CoreIocTest.Controllers { public class HomeController : Controller { private TestOptions _testOptions; private IUser _user; public HomeController( TestOptions testOptions, IUser user) { _testOptions = testOptions; _user = user; } public IActionResult Index() { var isNull = _testOptions.test == null; if (isNull) { _testOptions.test = new Test(); } if (!isNull) { _testOptions.IsChange = true; } var isNulluser = _user.test == null; if (isNulluser) { _user.test = new Test(); } if (!isNulluser) { _user.IsChange = true; } return View(); } } }
startup
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using CoreIocTest.Interface; using CoreIocTest.Models; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; namespace CoreIocTest { public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { var op = new TestOptions() { Name = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ssffff") }; services.AddScoped(s => op); services.AddScoped<IUser, User>(); services.AddControllersWithViews(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Home/Error"); } app.UseStaticFiles(); app.UseRouting(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); }); } } }
model
using Microsoft.Extensions.DependencyInjection; using System; using System.Collections.Generic; using System.Text; namespace CoreIocTest.Models { public class TestOptions { public string Name { get; set; } /// <summary> /// 默认选取的实现命 /// </summary> public bool IsChange { get; set; } = false; public Test test { get; set; } } public class Test { public int Id { get; set; } } }
using CoreIocTest.Models; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace CoreIocTest.Interface { public class User : IUser { public string Name { get; set; } /// <summary> /// 默认选取的实现命 /// </summary> public bool IsChange { get; set; } = false; public Test test { get; set; } } public interface IUser { public string Name { get; set; } /// <summary> /// 默认选取的实现命 /// </summary> public bool IsChange { get; set; } public Test test { get; set; } } }
三,我们看下调试结果
页面刷新第一次
刷新第二次
四 ,这个时候我们就奇怪了,为什么第二次请求isNull值改变了,不是说AddScoped是每次请求,容器的结果都是一个新实例么?
这个时候我们比较下isNull和isNulluser,isNull的IsChange值改变了,而isNulluser确是不变的,证明接口的实例每次都是一个新的实例,而直接将一个对象注入容器,每次构造注入拿出来的其实都是指向同一个地址的引用类型,实际上他们都是一个对象