详细解析 Prism 模块化(Modularity)核心组件的代码
下面详细解析 Prism 模块化Modularity核心组件的代码。Prism 的模块化允许将应用程序拆分为独立的、可组合的模块Module每个模块可以独立开发、测试、部署和按需加载。给出的代码实现了模块元数据存储、模块目录扩展、模块初始化和模块管理器等关键部分。一、整体架构概览Prism 模块化涉及以下角色IModule模块的接口包含RegisterTypes注册服务和OnInitialized初始化逻辑方法。ModuleInfo描述模块的元数据名称、类型、依赖、初始化模式、状态等。IModuleCatalog存储和管理ModuleInfo的集合支持依赖关系解析。IModuleInitializer负责创建模块实例并调用其生命周期方法。IModuleManager协调模块的加载、依赖解析和初始化过程。IModuleTypeLoader负责从远程位置下载模块程序集用于动态加载。以下代码实现了ModuleInfo、目录扩展方法、ModuleInitializer和ModuleManager。二、ModuleInfo 类publicpartialclassModuleInfo:IModuleInfo作用存储一个模块的元数据信息相当于模块的“描述符”。它会被添加到IModuleCatalog中供ModuleManager使用。属性属性说明ModuleName模块的唯一名称。ModuleType模块类型IModule实现类的程序集限定名称AssemblyQualifiedName。DependsOn当前模块依赖的其他模块的名称集合ModuleName。InitializationMode枚举值WhenAvailable应用启动时加载或OnDemand按需加载。Ref模块程序集的位置如文件路径或 URL用于动态下载。State模块当前状态NotStarted、LoadingTypes、ReadyForInitialization、Initializing、Initialized。构造函数提供多个重载方便创建ModuleInfo空构造主要用于序列化/XAML。指定名称、类型和依赖数组。直接传入模块Type自动提取名称和程序集限定名。支持指定初始化模式。设计要点DependsOn是Collectionstring允许 XAML 绑定和修改。实现了IModuleInfo接口以便其他组件如IModuleCatalog只依赖接口而非具体类。三、IModuleCatalogExtensions 静态类提供一系列扩展方法简化向IModuleCatalog添加模块的过程。典型方法示例publicstaticIModuleCatalogAddModuleT(thisIModuleCatalogcatalog,InitializationModemodeInitializationMode.WhenAvailable,paramsstring[]dependsOn)whereT:IModule作用通过泛型类型T添加模块。自动使用typeof(T).Name作为模块名称typeof(T).AssemblyQualifiedName作为类型。其他重载允许自定义模块名称、初始化模式、依赖项以及程序集引用位置refValue用于动态加载。分组支持publicstaticIModuleCatalogAddGroup(thisIModuleCatalogcatalog,InitializationModeinitializationMode,stringrefValue,paramsModuleInfo[]moduleInfos)作用添加一个模块组ModuleInfoGroup。如果目录实现了IModuleGroupsCatalog则可以批量添加模块并共享相同的Ref和InitializationMode。这对从同一位置下载多个模块的场景非常有用例如插件目录。设计优点类型安全避免字符串拼写错误。保持IModuleCatalog接口简洁将特定便捷方法放在扩展中。支持链式调用catalog.AddModuleMyModule().AddModuleOtherModule()。四、ModuleInitializer 类publicclassModuleInitializer:IModuleInitializer职责根据ModuleInfo创建模块实例。调用模块的RegisterTypes和OnInitialized方法。处理初始化过程中的异常。核心方法Initialize(IModuleInfo moduleInfo)publicvoidInitialize(IModuleInfomoduleInfo){IModulemoduleInstancenull;try{moduleInstanceCreateModule(moduleInfo);if(moduleInstance!null){moduleInstance.RegisterTypes(_containerExtension);moduleInstance.OnInitialized(_containerExtension);}}catch(Exceptionex){HandleModuleInitializationError(moduleInfo,moduleInstance?.GetType().Assembly.FullName,ex);}}先通过CreateModule解析模块实例。然后依次调用RegisterTypes注册模块内的服务到容器和OnInitialized执行初始化逻辑如导航注册、事件订阅。捕获任何异常并调用HandleModuleInitializationError包装为ModuleInitializeException抛出。CreateModuleprotectedvirtualIModuleCreateModule(stringtypeName){TypemoduleTypeType.GetType(typeName);if(moduleTypenull)thrownewModuleInitializeException(...);return(IModule)_containerExtension.Resolve(moduleType);}使用Type.GetType解析类型如果程序集已加载。通过容器解析实例这允许模块的构造函数有依赖项由容器自动注入。设计优点可重写CreateModule和HandleModuleInitializationError支持自定义创建逻辑如从非标准位置加载和错误处理。依赖注入容器被用于创建模块保证了模块本身也能享受 DI 的好处。五、ModuleManager 类publicpartialclassModuleManager:IModuleManager,IDisposable职责管理模块的整个生命周期从目录读取模块 → 处理依赖 → 触发下载若需要→ 初始化模块。支持按需加载LoadModule。提供进度和完成事件ModuleDownloadProgressChanged、LoadModuleCompleted。依赖IModuleInitializer用于初始化模块。IModuleCatalog提供模块列表和依赖关系。IModuleTypeLoader集合实际执行程序集下载的类型加载器由派生类或容器提供代码中ModuleTypeLoaders属性未显示但通过GetTypeLoaderForModule使用。核心流程1. 应用启动Run()publicvoidRun(){ModuleCatalog.Initialize();LoadModulesWhenAvailable();}调用目录的Initialize允许目录延迟加载如从配置文件读取。加载所有初始化模式为WhenAvailable的模块。2. 加载就绪模块LoadModulesWhenAvailable→LoadModuleTypes→LoadModulesThatAreReadyForLoadLoadModuleTypes遍历所有WhenAvailable模块及其依赖若模块状态为NotStarted检查是否需要检索ModuleNeedsRetrieval如果Type.GetType返回null程序集未加载则调用BeginRetrievingModule启动下载否则标记为ReadyForInitialization。LoadModulesThatAreReadyForLoad循环处理从目录中找到所有状态为ReadyForInitialization且依赖都已初始化AreDependenciesLoaded的模块。将状态改为Initializing调用InitializeModule然后继续循环直到没有可初始化的模块。这保证了依赖顺序只有当一个模块的所有依赖模块都已Initialized后它才会被初始化。3. 按需加载LoadModule(string moduleName)根据模块名称找到对应的ModuleInfo。调用CompleteListWithDependencies目录扩展方法获取该模块及其所有依赖递归。然后调用LoadModuleTypes与上面相同流程会触发下载和初始化。4. 动态下载模块BeginRetrievingModule通过GetTypeLoaderForModule找到能处理该模块的IModuleTypeLoader。设置状态为LoadingTypes。订阅加载器的LoadModuleCompleted和ModuleDownloadProgressChanged事件。调用moduleTypeLoader.LoadModuleType(moduleInfo)开始异步下载。5. 下载完成回调IModuleTypeLoader_LoadModuleCompleted若无错误将模块状态改为ReadyForInitialization然后调用LoadModulesThatAreReadyForLoad()继续初始化。若有错误触发LoadModuleCompleted事件如果错误未被处理e.IsErrorHandled false则调用HandleModuleTypeLoadingError抛出异常。6. 初始化模块InitializeModule状态必须为Initializing。调用moduleInitializer.Initialize(moduleInfo)。状态改为Initialized触发LoadModuleCompleted事件。依赖检查AreDependenciesLoaded通过ModuleCatalog.GetDependentModules获取当前模块依赖的模块列表。检查这些依赖是否都处于Initialized状态。类型加载器选择GetTypeLoaderForModule遍历ModuleTypeLoaders集合通常由派生类或模块目录提供找到第一个能加载该模块的加载器。如果找不到抛出ModuleTypeLoaderNotFoundException。资源释放Dispose遍历所有IModuleTypeLoader若其实现了IDisposable则释放。事件ModuleDownloadProgressChanged透传加载器的进度事件。LoadModuleCompleted模块加载完成成功或失败时触发。六、模块化完整工作流总结模块注册通过IModuleCatalog通常在 App.xaml.cs 或启动代码中添加模块可以使用扩展方法AddModuleT或AddGroup。应用启动ModuleManager.Run()被调用通常在 PrismApplication 内部。加载可用模块查找所有InitializationMode.WhenAvailable的模块及其依赖。动态加载对于程序集未加载的模块使用IModuleTypeLoader下载程序集例如从网络或本地文件系统。依赖顺序初始化等待所有依赖模块初始化完成后才初始化当前模块。模块初始化ModuleInitializer创建模块实例调用RegisterTypes和OnInitialized。按需加载任何代码调用moduleManager.LoadModule(ModuleName)将触发该模块及其依赖的下载和初始化。七、设计模式与原则体现依赖倒置ModuleManager依赖IModuleCatalog、IModuleInitializer、IModuleTypeLoader等抽象而非具体实现。单一职责ModuleInfo仅存储元数据ModuleInitializer只负责创建和调用模块ModuleManager协调流程。开闭原则通过扩展方法为IModuleCatalog添加功能无需修改原始接口ModuleManager的可重写方法如HandleModuleTypeLoadingError允许子类扩展行为。观察者模式通过事件LoadModuleCompleted、ModuleDownloadProgressChanged通知进度和结果。策略模式IModuleTypeLoader定义了不同加载策略如从文件、从网络的统一接口ModuleManager根据模块信息选择合适的策略。组合模式ModuleInfoGroup代码未完整给出但在扩展中引用允许将一组模块作为一个组来处理。八、注意事项代码中的ModuleTypeLoaders集合未在当前文件中定义通常由派生类如ModuleManager的子类或通过容器注入提供。CompleteListWithDependencies是IModuleCatalog的扩展方法需要手动实现或由框架提供它递归收集模块及其所有依赖。模块的RegisterTypes通常用于向容器注册模块内的服务如视图、服务接口而OnInitialized用于执行启动后逻辑如注册导航、订阅事件。整个设计支持后台下载和按需加载适用于大型应用或插件化架构。通过以上组件Prism 提供了一个灵活、强大的模块化框架让开发者能够轻松构建可扩展、可维护的 Xamarin.Forms / MAUI 应用程序。