windows-services – 首先是TopShelf,Ninject和EF代码的Ninject范围问题
我目前正在使用TopShelf和Ninject来创建 Windows服务.我有以下代码使用TopShelf设置Windows服务: static void Main(string[] args) { using (IKernel kernel = new StandardKernel(new NinjectDependencyResolver())) { Settings settings = kernel.Get<Settings>(); var host = HostFactory.New(x => { x.Service<BotService>(s => { s.ConstructUsing(name => new BotService(settings.Service.TimeInterval)); s.WhenStarted(ms => ms.Start()); s.WhenStopped(ms => ms.Stop()); }); x.RunAsNetworkService(); x.SetServiceName(settings.Service.ServiceName); x.SetDisplayName(settings.Service.DisplayName); x.SetDescription(settings.Service.Description); }); host.Run(); } } 这是Windows服务完成所有工作背后的对象: public class BotService { private readonly Timer timer; public BotService(double interval) { this.timer = new Timer(interval) { AutoReset = true }; this.timer.Elapsed += (sender,eventArgs) => Run(); } public void Start() { this.timer.Start(); } public void Stop() { this.timer.Stop(); } private void Run() { IKernel kernel = new StandardKernel(new NinjectDependencyResolver()); Settings settings = kernel.Get<Settings>(); if (settings.Service.ServiceType == 1) { // The interface implementation has constructor injection of IUnitOfWork and IMyRepository kernel.GetAll<IExternalReportService>().Each(x => x.Update()); } if (settings.Service.ServiceType == 2) { // The interface implementation has constructor injection of IUnitOfWork and IMyRepository kernel.GetAll<IExternalDataService>().Each(x => x.GetData()); } kernel.Get<IUnitOfWork>().Dispose(); kernel.Dispose(); } } 这些是Ninject绑定: public class NinjectDependencyResolver : NinjectModule { public override void Load() { Settings settings = CreateSettings(); ConnectionStringSettings connectionStringSettings = ConfigurationManager.ConnectionStrings["DB"]; Bind<IDatabaseFactory>().To<DatabaseFactory>() .InThreadScope() .WithConstructorArgument("connectionString",connectionStringSettings.Name); Bind<IUnitOfWork>().To<UnitOfWork>(); Bind<IMyRepository>().To<MyRepository>(); Bind<IExternalReportService>().To<ReportService1>(); Bind<IExternalReportService>().To<ReportService2>(); Bind<IExternalDataService>().To<DataService1>(); Bind<IExternalDataService>().To<DataService2>(); Bind<Settings>().ToConstant(settings); } private Settings CreateSettings() { // Reads values from app.config and returns object with settings } } 首先让我说我对这段代码不满意.当应用程序启动时,会创建一个内核实例,从中获取设置中的值,并使用TopShelf使用BotService对象创建Windows服务. 每次定时器事件触发时,都会执行Run()方法.这里创建了另一个内核实例,它再次读取设置,并根据值获取接口的所有实现并执行相应的方法.这些实现中的每一个都有一个构造函数,其中注入IUnitOfWork和IMyRepository以进行数据访问. 当方法完成后,我处理上下文并处理内核. 为什么我这样设置?最初我只在Main中创建了一个内核,并使用BotService中的构造函数来注入实现,而不是创建另一个内核实例.问题是DatabaseFactory需要InSingletonScope或InThreadScope才能工作. 如果我使用InSingeltonScope,上下文将变得陈旧,最终问题将开始蔓延到上下文无效的地方.如果我使用InThreadScope,我会遇到同样的问题,因为一旦线程完成,它就不会处理对象.最终Run()使用了以前使用过的线程和异常,因为我已经处理了Context.如果我删除了我处理上下文的代码行,那么我们遇到与InSingletonScope相同的问题,当重新使用该线程时,我们最终会遇到陈旧的上下文. 这导致了当前的代码,我保证每个Time Run()都被执行,上下文一直存在,直到它完成它被处理的地方,因为内核也被处理掉了我确保下次使用相同的线程时我们得到自重新创建内核以来的新上下文(至少我认为这是正在发生的事情). 我的Ninject技能并不是那么先进,关于如何解决这个问题的信息非常有限.我认为正确的方法是仅在Main中创建一个内核,然后能够通过构造函数将我需要的内容注入到BotService对象中.但同时需要为每个Run()创建Context,以避免在我使用上述方法之一时使用此方法时会发生的过时上下文. 如何修改上面的示例以便它是正确的?我目前正在使用Ninject 2.2.1.4. 首先,让我尝试将您的问题提炼一点.听起来像你有一个需要自定义范围的依赖项(DatabaseFactory)(或其他人可能将其称为生命周期).听起来我想要在单次执行Run期间返回相同的DatabaseFactory实例.如果这是正确的,我认为您应该能够通过以下两种方式之一完成此任务: >如果您不介意每次执行Run时刷新所有实例: private StandardKernel _kernel /* passed into constructor */; public void Run() { using (var block = _kernel.BeginBlock()) { var settings = block.Get<Settings>(); if (settings.Service.ServiceType == 1) { // The interface implementation has constructor injection of IUnitOfWork and IMyRepository block.GetAll<IExternalReportService>().Each(x => x.Update()); } if (settings.Service.ServiceType == 2) { // The interface implementation has constructor injection of IUnitOfWork and IMyRepository block.GetAll<IExternalDataService>().Each(x => x.GetData()); } } } >如果您只希望为每次执行刷新特定实例,则应该能够使用自定义范围对象完成此操作(查看InScope()方法和this post from Nate).不幸的是,您可能会遇到许多多线程问题,因为Timer可能会在另一个线程运行完毕之前调用Run. (编辑:台州站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- windows-mobile – Visual Studio 2010 Professional Beta
- WIN10家庭中文版远程提示要求的函数不支持 win10家庭版提示
- windows – 以MONO Runtime为目标导致Xamarin Build失败
- .net – 加载Azure Storage 2.0时出错 – 无法加载Microsof
- windows – 如何成功更改执行策略并启用PowerShell脚本的执
- 在非Qt应用程序中使用基于Qt的DLL
- 为什么WPF在不同版本的Windows上呈现不同?
- windows-installer – 安装期间的错误代码2753
- window python2.7 ImportError: No module named MySQLdb
- WiX – 通过检查修订来防止降级
- Qt 5 QML应用程序,包含许多Windows或复杂的UI
- tfs – 在测试用例通过或失败时发送电子邮件警报
- windows-services – 首先是TopShelf,Ninject和E
- windows10 安装python.msi出现error 2502/2503解
- 批处理文件 – Windows批处理将记录添加到主机文
- xaml – 属性内容设置多次
- Microsoft Unit Testing Framework for C++
- 在[Windows Subsystem for Linux]中安装perl模块
- Windows Phone 7 – Windows Phone开发Visual St
- 在没有Microsoft.NET.Sdk.Web的情况下使用Razor