asp.net-mvc – Autofac(MVC EF SignalR Hangfire)生命周期范围
我有一个ASP.NET MVC项目,它使用Entity Framwork,SignalR和Hangfire作业.
我的主(根)容器以这种方式定义: builder.RegisterType<DbContext>().InstancePerLifetimeScope(); // EF Db Context builder.RegisterType<ChatService>().As<IChatService>().SingleInstance(); // classic "service",has dependency on DbContext builder.RegisterType<ChatHub>().ExternallyOwned(); // SignalR hub builder.RegisterType<UpdateStatusesJob>().InstancePerDependency(); // Hangfire job builder.RegisterType<HomeController>().InstancePerRequest(); // ASP.NET MVC controller IContainer container = builder.Build(); 对于MVC,我使用的是Autofac.MVC5 nuget包.依赖性解析器: DependencyResolver.SetResolver(new AutofacDependencyResolver(container)); 对于SignalR,我正在使用Autofac.SignalR nuget包.依赖性解析器: GlobalHost.DependencyResolver = new Autofac.Integration.SignalR.AutofacDependencyResolver(container); 我的signalR hub以这种方式实例化(http://autofac.readthedocs.org/en/latest/integration/signalr.html#managing-dependency-lifetimes): private ILifetimeScope _hubScope; protected IChatService ChatService; public ChatHub(ILifetimeScope scope) { _hubScope = scope.BeginLifetimeScope(); // scope ChatService = _hubScope.Resolve<IChatService>(); // this service is used in hub methods } protected override void Dispose(bool disposing) { // Dipose the hub lifetime scope when the hub is disposed. if (disposing && _hubScope != null) { _hubScope.Dispose(); } base.Dispose(disposing); } 对于Hangfire,我使用的是Hangfire.Autofac包: config.UseActivator(new AutofacJobActivator(container)); 作业以这种方式实例化: private readonly ILifetimeScope _jobScope; protected IChatService ChatService; protected BaseJob(ILifetimeScope scope) { _jobScope = scope.BeginLifetimeScope(); ChatService = _jobScope.Resolve<IChatService>(); } public void Dispose() { _jobScope.Dispose(); } 问题/问题: 可以这样做,还是我错过了什么? 更新1: 思考(睡过头)后,我想我有两个选择.我仍然希望保持“每个请求的会话”(“每个集群的会话”,“每个作业的会话”). 选项1: 更改所有服务将具有InstancePerLifetimeScope.实例化服务并不昂贵.对于维护某种状态的服务,我将创建另一个“存储”(类),它将是SingleInstance并且不依赖于session(DbContext).我认为这也适用于枢纽和工作. 选项2: 创建@Ric .Net建议的某种工厂.像这样的东西: public class DbFactory: IDbFactory { public MyDbContext GetDb() { if (HttpContext.Current != null) { var db = HttpContext.Current.Items["db"] as MyDbContext; if (db == null) { db = new MyDbContext(); HttpContext.Current.Items["db"] = db; } return db; } // What to do for jobs and hubs? return new MyDbContext(); } } protected void Application_EndRequest(object sender,EventArgs e) { var db = HttpContext.Current.Items["db"] as MyDbContext; if (db != null) { db.Dispose(); } } 我认为这对MVC有用,但我不知道它是否适用于集线器(每个集线器调用是集线器的新实例)和作业(每次运行的作业都是作业类的新实例) . 我倾向于选项1.你怎么看? 非常感谢! 解决方法
我对AutoFac完全缺乏经验.但引起我注意的是:
你在这里基本上说的是: “我的汽车是由依赖车库的汽车公司进行维修的,但每次我带车时我都希望车库成为新车”. 当您在其他组件中注入(完全构建实例,包括依赖项)ChatService时,当然还会构建其他依赖项,无论它们是否具有其他类型的生活方式.当创建一个比它注入的对象更短的生命周期的对象时,你创建了一个所谓的’captive dependency‘ 在ChatService中获取DbContext的新“实例”的唯一方法不是注入DbContext本身,而是注入一个DbContextFactory,只要你使用它就会为你创建DbContext. 实现看起来像: public class DbContextFactory { public DbContext Create() { return new DbContext(); } } //usage: public class ChatService { private readonly DbContextFactory dbContextFactory; public ChatService(DbContextFactory dbContextFactory) { this.dbContextFactory = dbContextFactory; } public void SomeMethodInChatService() { using (var db = this.dbContextFactory.Create()) { //do something with DbContext } } } 可以使用Singleton Lifestyle在AutoFac中注册DbContextFactory. 然而,这可能不是你的目标.因为在这种情况下,每次使用DbContext时都会得到一个新的.另一方面,新的DbContext可能是最安全的方法,你可以阅读here. 这个伟大的答案值得阅读,原因不止一个,因为它解释了如何使用command / handler pattern,这应该非常适合您的情况. 这将使您的聊天服务完全不知道DbContext,它改进了应用程序的’SOLID‘设计,并创建了测试ChatService的可能性,这是在直接注入DbContext或DbContextFactory时几乎可以撤销的. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- asp.net – 为什么Response.BufferOutput = False,不工作?
- asp.net – 考虑到N2 CMS,但担心性能.这是否合理?
- .net – 为什么我的剃刀视图抱怨“}预计”升级到剃刀2/mvc
- asp.net-mvc – ASP.Net MVC自定义模型绑定说明
- asp.net – 如何访问Global.asax静态成员?
- 从asp.net中的gridview获取已检查的行
- ASP.NET MVC 5 – RazorGenerator与发布期间的发布预编译
- asp.net-mvc – ASP.NET MVC中依赖于语言的路由
- asp.net-mvc – 在存储库中使用Blocks有什么问题?
- asp.net-mvc-4 – 自定义错误在我的MVC 4应用程序中无效