最近.net core可以跨平臺了,這是一個偉大的事情,為了可以趕上兩年以後的跨平臺部署大潮,我也加入到了學習之列。今天研究的是依賴註入,但是我發現一個問題,困擾我很久,現在我貼出來,希望可以有人幫忙解決或回覆一下。 背景:我測試.net自帶的依賴註入生命周期,一共三個:Transient、Scop ...
最近.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來了,我們又可以通過學習來漲工資了。