IOptionsWritable.Update()在WinForm类中无法写入json文件问题
问题原因
核心是你运行时用的FormConfiguration实例根本不是DI容器解析出来的,没拿到合法的IOptionsWritable<SomeSectionClass>实例,调用Update时自然写不进配置,而IOptionsWriter库内部做了容错,这种情况不会抛异常。
90%的情况都是你打开配置窗体的时候直接写了new FormConfiguration()手动创建实例,完全没走DI注入流程。WinForms窗体为了适配设计器一般都会留无参构造,你手动new的时候调用的就是这个无参构造,类里的_someWritableOptions字段要么是null(你可能加了空值判断跳过了执行,所以没抛空引用异常),要么是你为了过编译手动塞了个空的占位实现,根本没绑定到实际加载了appsettings.json的配置对象,Update操作等于啥也没干。
剩下10%的可能是你用的IOptionsWriter版本默认把IOptionsWritable注册为Scoped生命周期,你在Program里手动建的scope在主窗体运行后被释放,后续拿到的失效实例调用Update会静默失败。
你虽然在DI里注册了services.AddSingleton<IFormConfiguration, FormConfiguration>(),但只要你没从容器拿实例、自己new窗体,这个注册就完全不生效。
修复步骤
- 先验证实例一致性
在SomePresenter.OnSomeEvent和FormConfiguration.BtnSave_OnClick里分别打调试断点,运行时看两个方法里_someWritableOptions的哈希码,两个值不一样就坐实是手动new窗体的问题。 - 改掉手动new窗体的逻辑
所有用到FormConfiguration的地方都不许手动new,统一从DI容器获取:
- 在主窗体FormMain的构造函数里直接注入
IFormConfiguration,存成私有字段,要打开配置页的时候直接对这个字段调用Show/ShowDialog就行。 - 要是必须留无参构造给设计器用,就加个DesignMode判断,只有设计器运行的时候才走无参构造,运行时全走DI的带参构造,别在无参构造里给
_someWritableOptions塞无效的占位对象。
- (可选,兼容旧版库)修改服务生命周期
调用ConfigureWritable的时候手动指定生命周期为单例,避免Scoped实例释放导致的写入失败:
services.ConfigureWritable<SomeSectionClass>("SomeSection", ServiceLifetime.Singleton);
- 不用排查文件权限问题,毕竟你在Presenter里能正常写入,说明文件本身和路径配置都没有问题。
内容的提问来源于stack exchange,提问作者Maakarov
相关产品推荐
相关产品推荐

