# RaySourceOperateView 集成技术路线 ## 整体架构 采用 **DLL 直接引用 + Prism DI 容器手动注册 + AutoWireViewModel 自动装配** 的集成方式。 DLL 提供完整的 MVVM 三层(View / ViewModel / Service),主项目负责 DI 注册和 XAML 布局嵌入,数据通过注入的服务接口和 Prism EventAggregator 在两侧流动。 --- ## 分层说明 ### 1. DLL 引用层 `XP.Hardware.RaySource.dll` 放置于 `Libs/Hardware/` 目录,通过 `.csproj` 的 `` 引用。 DLL 内部包含: | 类型 | 名称 | 说明 | |------|------|------| | UserControl | `RaySourceOperateView` | 射线源操作界面 | | ViewModel | `RaySourceOperateViewModel` | 对应 ViewModel | | 服务接口/实现 | `IRaySourceService` / `RaySourceService` | 射线源业务逻辑 | | 工厂 | `IRaySourceFactory` / `RaySourceFactory` | 策略工厂,支持 Comet225/320、Spellman225 | | 服务 | `IFilamentLifetimeService` | 灯丝寿命管理 | | 配置模型 | `RaySourceConfig` | 从 App.config 加载的配置 | --- ### 2. DI 注册层(App.xaml.cs → AppBootstrapper) 主项目在 `RegisterTypes()` 中**手动注册** DLL 内所有服务,未走 Prism 的 `ConfigureModuleCatalog` 自动模块加载,目的是避免模块加载顺序问题,确保 DryIoc 容器在 Shell 创建前已具备所有依赖。 ```csharp // 注册 ViewModel(供 ViewModelLocator 自动装配) containerRegistry.Register(); // 注册配置(从 App.config 读取 RaySource:xxx 键值) var raySourceConfig = XP.Hardware.RaySource.Config.ConfigLoader.LoadConfig(); containerRegistry.RegisterInstance(raySourceConfig); // 注册核心服务(全部单例) containerRegistry.RegisterSingleton(); containerRegistry.RegisterSingleton(); containerRegistry.RegisterSingleton(); ``` --- ### 3. XAML 嵌入层(MainWindow.xaml) 通过 XML 命名空间直接引用 DLL 中的 View: ```xml xmlns:views1="clr-namespace:XP.Hardware.RaySource.Views;assembly=XP.Hardware.RaySource" ``` 在主窗口右侧面板顶部(Grid.Row="0",固定高度 250px)放置控件: ```xml ``` 控件内部已设置 `prism:ViewModelLocator.AutoWireViewModel="True"`,Prism 按命名约定自动从 DI 容器解析 `RaySourceOperateViewModel` 并绑定为 DataContext。 --- ### 4. 数据传递路线 数据流分四条路径: **路径 A:配置数据(启动时,单向下行)** ``` App.config (RaySource:xxx 键值) → ConfigLoader.LoadConfig() → RaySourceConfig 实例 → 注入到 RaySourceService / RaySourceOperateViewModel ``` App.config 中的关键配置项: ```xml ``` **路径 B:用户操作(UI → DLL 服务层)** ``` RaySourceOperateView(按钮点击) → RaySourceOperateViewModel(Command 绑定) → IRaySourceService.SetVoltageAsync() / TurnOnAsync() / ... → IXRaySource(具体策略实现,如 Comet225) → 硬件通讯(B&R PVI / BR.AN.PviServices.dll) ``` **路径 C:状态回传(DLL 服务层 → UI)** ``` 硬件状态轮询(StatusPollingInterval = 500ms) → RaySourceService 内部更新 → RaySourceOperateViewModel 属性变更(INotifyPropertyChanged) → RaySourceOperateView 数据绑定自动刷新 同时: → AppStateService 订阅 IRaySourceService 事件 → 更新 RaySourceState(IsOn, Voltage, Power) → Dispatcher.BeginInvoke 调度到 UI 线程 → 其他 ViewModel 通过 IAppStateService 读取全局射线源状态 ``` `RaySourceState` 为不可变 record,定义于 `Models/StateModels.cs`: ```csharp public record RaySourceState( bool IsOn, // 开关状态 double Voltage, // 电压 (kV) double Power // 功率 (W) ) { public static readonly RaySourceState Default = new(false, 0, 0); } ``` **路径 D:跨模块事件通讯(Prism EventAggregator)** ``` DLL 内部发布事件(XP.Hardware.RaySource.Abstractions.Events): XrayStateChangedEvent — 射线开关状态变化 StatusUpdatedEvent — 实时电压/电流数据 ErrorOccurredEvent — 错误通知 OperationResultEvent — 操作结果回调 主项目任意 ViewModel 订阅示例: _eventAggregator.GetEvent().Subscribe(data => { ... }); ``` --- ### 5. 完整依赖关系 ``` RaySourceOperateView(DLL 中的 UserControl) └─ AutoWire → RaySourceOperateViewModel(DLL,主项目注册到 DI) ├─ IRaySourceService ← 单例,DLL 实现 ├─ RaySourceConfig ← App.config 加载 ├─ IFilamentLifetimeService ← 单例,DLL 实现 ├─ IEventAggregator ← Prism 内置 ├─ ILoggerService ← 主项目 LoggerServiceAdapter 适配 Serilog └─ ILocalizationService ← 主项目注册,DLL 消费 ``` --- ### 6. 资源释放 `App.OnExit()` 中显式从容器解析并释放资源: ```csharp var appStateService = bootstrapper.Container.Resolve(); appStateService?.Dispose(); var raySourceService = bootstrapper.Container.Resolve(); raySourceService?.Dispose(); ``` 确保硬件连接在应用退出时正确断开。