Skip to content

Prism容器中配置文件热更

约 682 字大约 2 分钟

WPF

2024-09-26

主项目中

//appsettings.json
{
    "ConfigurationScanDirectories": ["Configuration", "Config"] // 扫描项目中所有配置文件json文件夹(自动合并该文件夹里面所有json文件)
}
//app.xaml.cs中注册配置文件
private static IConfiguration BuildConfig()
{
    var configurationBuilder = new ConfigurationBuilder()
           .SetBasePath(Directory.GetCurrentDirectory())
           .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
    var configuration = configurationBuilder.Build();

    var scanDirs = configuration.GetConfig<string[]>("ConfigurationScanDirectories");
    if (scanDirs == null) throw new Exception("配置文件节点未找到");
    foreach (string dir in scanDirs)
    {
        string dirPath = Path.Combine(Directory.GetCurrentDirectory(), dir);
        if (Directory.Exists(dirPath))
        {
            var files = Directory.GetFiles(dirPath, "*.json");
            foreach (var file in files) configurationBuilder.AddJsonFile(file, optional: true, reloadOnChange: true);
        }
    }
    configuration = configurationBuilder.Build();
    return configuration;
}

模块中

//Scanpara.json
{
    "ScanPara": {
        "IsDebug": true //调试模式
    }
}
 public class ScanPara
 {
     public bool IsDebug { get; set; }
 }
 public class ScanModule : IModule
 {
     IConfiguration _Configuration;
     public void OnInitialized(IContainerProvider containerProvider)
     {
     }
	 public void RegisterTypes(IContainerRegistry containerRegistry)
	 {
		 containerRegistry.Register<ScanPara>(() => _Configuration.GetConfig<ScanPara>("ScanPara"));//Register使用register注入,可热更
	 }
}

使用

public partial class SlideManagement : UserControl
{
	private  Func<ScanPara> _ScanParaFactory;

	public SlideManagement(Func<ScanPara> _scanParaFactory)
	{
		_ScanParaFactory = _scanParaFactory;
	}
	private void praa_Click(object sender, RoutedEventArgs e)
	{
	/*_scanParaFactory 被调用时,实际上执行的是传给它的工厂方法,这个方法可以每次创建并返回一个新的 ScanPara 对象。通过调用获得了一个新的 ScanPara 实例,而不是缓存的实例,这就实现了每次访问最新配置的目的。*/
	    var ScanPara = _ScanParaFactory();
	}
}

解析

关于Func<Entity>

Func<Entity>是一个委托类型,表示一个方法,该方法没有参数并返回一个 Entity 对象。

  1. 为什么调用_ScanParaFactory()就获取了新对象

    • 首先通过Register()注入了瞬时对象
    • scanParaFactory`  被调用时,实际上执行的是传给它的工厂方法,这个方法可以每次创建并返回一个新的  ScanPara  对象。通过调用获得了一个新的  ScanPara  实例,而不是缓存的实例,这就实现了每次访问最新配置的目的。
  2. 为什么注入的是ScanPara构造函数中可以使用Func<ScanPara> 接收?

    • 因为Prism框架中,依赖注入和容器注册的机制允许你注入所需的依赖项。未明确地在容器中注册Func<ScanPara>的情况下,实际是通过注册ScanPara时的函数注入方式实现的,这是因为 Prism 和其底层依赖注入容器(如 Unity, DryIoc 等)能够根据已注册的类型自动生成并注入  Func<T>  这样的工厂函数。
    • containerRegistry.Register<ScanPara>(() => _Configuration.GetConfig<ScanPara>("ScanPara"));注册时实际上是在注册工厂方法,该方法会动态地根据配置创建并返回一个新的ScanPara实例。这意味着依赖注入容器知道如何创建ScanPara实例。更妙的是,依赖注入容器同时可以自动为类似Func<ScanPara>的工厂方法生成实现。实际执行的是_scanParaFactory = () => container.Resolve<ScanPara>(); 妙妙妙啊!