asp.net core 依赖注入问题
最近.net core可以跨平台了,这是一个伟大的事情,为了可以赶上两年以后的跨平台部署大潮,我也加入到了学习之列。今天研究的是依赖注入,但是我发现一个问题,困扰我很久,现在我贴出来,希望可以有人帮忙解决或回复一下。
背景:我测试.net自带的依赖注入生命周期,一共三个:Transient、Scope、Single三种,通过一个GUID在界面展示,但是我发现scope和single的每次都是相同的,并且single实例的guid值每次都会改变。
通过截图可以看到scope和Single每次浏览器刷新都会改变,scope改变可以理解,就是每次请求都会改变。但是single 每次都改变就不对了。应该保持一个唯一值才对。
Program.cs代码:启动代码
1 namespace CoreStudy 2 { 3 public class Program 4 { 5 public static void Main(string[] args) 6 { 7 Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); 8 var host = new WebHostBuilder() 9 .UseKestrel()//使用服务器serve 10 .UseContentRoot(Directory.GetCurrentDirectory()) 11 .UseIISIntegration()//使用IIS 12 .UseStartup<Startup>()//使用起始页 13 .Build();//IWebHost 14 15 host.Run();//构建用于宿主应用程序的IWebHost 16 //然后启动它来监听传入的HTTP请求 17 } 18 } 19 }
Startup.cs 文件代码
1 namespace CoreStudy 2 { 3 public class Startup 4 { 5 public Startup(IHostingEnvironment env, ILoggerFactory logger) 6 { 7 var builder = new ConfigurationBuilder() 8 .SetBasePath(env.ContentRootPath) 9 .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) 10 .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true) 11 .AddEnvironmentVariables(); 12 builder.AddInMemoryCollection(); 13 14 } 15 // This method gets called by the runtime. Use this method to add services to the container. 16 // For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=398940 17 public void ConfigureServices(IServiceCollection services) 18 {//定义服务 19 services.AddMvc(); 20 services.AddLogging(); 21 services.AddTransient<IPersonRepository, PersonRepository>(); 22 services.AddTransient<IGuidTransientAppService, TransientAppService>(); 23 24 services.AddScoped<IGuidScopeAppService, ScopeAppService>(); 25 26 services.AddSingleton<IGuidSingleAppService, SingleAppService>(); 27 } 28 29 // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 30 public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IApplicationLifetime appLifetime) 31 {//定义中间件 32 33 if (env.IsDevelopment()) 34 { 35 app.UseDeveloperExceptionPage(); 36 app.UseBrowserLink(); 37 app.UseDatabaseErrorPage(); 38 39 } 40 else 41 { 42 app.UseExceptionHandler("/Home/Error"); 43 } 44 app.UseStaticFiles(); 45 //app.UseStaticFiles(new StaticFileOptions() { 46 // FileProvider=new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(),@"staticFiles")), 47 // RequestPath="/staticfiles" 48 // }); 49 //默认路由设置 50 app.UseMvc(routes => 51 { 52 routes.MapRoute(name: "default", template: "{controller=Person}/{action=Index}/{id?}"); 53 }); 54 55 56 } 57 } 58 }
请注意22-26行,注册了三种不同生命周期的实例,transientService、scopeService以及singleService。
对应的接口定义:
1 namespace CoreStudy 2 { 3 public interface IGuideAppService 4 { 5 Guid GuidItem(); 6 } 7 public interface IGuidTransientAppService:IGuideAppService 8 { } 9 public interface IGuidScopeAppService:IGuideAppService 10 { } 11 public interface IGuidSingleAppService:IGuideAppService 12 { } 13 14 } 15 16 namespace CoreStudy 17 { 18 public class GuidAppService : IGuideAppService 19 { 20 private readonly Guid item; 21 public GuidAppService() 22 { 23 item = Guid.NewGuid(); 24 } 25 public Guid GuidItem() 26 { 27 return item; 28 } 29 30 } 31 public class TransientAppService:GuidAppService,IGuidTransientAppService 32 { 33 34 } 35 36 public class ScopeAppService:GuidAppService,IGuidScopeAppService 37 { } 38 public class SingleAppService:GuidAppService,IGuidSingleAppService 39 { } 40 }
代码很简单,只是定义了三种不同实现类。
控制器中 通过构造函数注入方式注入:
1 namespace CoreStudy.Controllers 2 { 3 /// <summary> 4 /// 控制器方法 5 /// </summary> 6 public class PersonController : Controller 7 { 8 private readonly IGuidTransientAppService transientService; 9 private readonly IGuidScopeAppService scopedService; 10 private readonly IGuidSingleAppService singleService; 11 12 13 private IPersonRepository personRepository = null; 14 /// <summary> 15 /// 构造函数 16 /// </summary> 17 /// <param name="repository"></param> 18 public PersonController(IGuidTransientAppService trsn, IGuidScopeAppService scope, IGuidSingleAppService single) 19 { 20 this.transientService = trsn; 21 this.scopedService = scope; 22 this.singleService = single; 23 } 24 25 /// <summary> 26 /// 主页方法 27 /// </summary> 28 /// <returns></returns> 29 public IActionResult Index() 30 { 31 ViewBag.TransientService = this.transientService.GuidItem(); 32 33 ViewBag.scopeService = this.scopedService.GuidItem(); 34 35 ViewBag.singleservice = this.scopedService.GuidItem(); 36 37 return View(); 38 } 39 40 41 } 42 }
控制器对应的视图文件Index.cshtm
1 @{ 2 ViewData["Title"] = "Person Index"; 3 Layout = null; 4 } 5 6 <form asp-controller="person" method="post" class="form-horizontal" role="form"> 7 <h4>创建账户</h4> 8 <hr /> 9 <div class="row"> 10 <div class="col-md-4"> 11 <span>TransientService:</span> 12 @ViewBag.TransientService 13 </div> 14 </div> 15 <div class="row"> 16 <span>Scope</span> 17 @ViewBag.ScopeService 18 </div> 19 <div class="row"> 20 <span>Single</span> 21 @ViewBag.SingleService 22 </div> 23 <div class="col-md-4"> 24 @await Component.InvokeAsync("Greeting"); 25 </div> 26 </form>
其他无关代码就不粘贴了,希望各位能给个解释,我再看一下代码,是否哪里需要特殊设置。
答案在PersonController 类的 35行,此问题主要是为了能够更好的理解依赖注入
.Net Core来了,我们又可以通过学习来涨工资了。
有人的地方就有政治,有政治就有斗争,但我讨厌政治,讨厌无休止的迎合。