You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Prism的Revit插件:自动生成对话框名称常量类方案咨询

解决方案与代码异味分析

一、代码生成器的可行性实现

可以通过Roslyn源代码生成器实现需求,针对你提到的两种场景,具体实现思路如下:

1. 检测UI项目新增对话框子类

编写Roslyn分析器扫描UI项目中继承自Prism对话框基类(如IDialogAware、DialogWindow或自定义对话框基类)的类型,自动生成静态类的常量字段:

  • 字段名可通过类型名转换生成(比如去掉Dlg前缀、转为大驼峰格式)
  • 字段值默认使用类型的FullName(Prism默认的对话框注册名称),若有自定义名称需求,可通过给对话框类添加特性(如[DialogAlias("CustomName")])来指定

2. 检测RegisterDialog注册调用

扫描项目中所有IContainerRegistry.RegisterDialog<,>()的调用:

  • 提取泛型参数中的视图类型,获取其默认注册名称或特性指定的自定义名称
  • 若调用的是带自定义名称的重载(如RegisterDialog<,>("CustomName")),则直接提取字符串常量作为字段值

生成的静态类示例:

public static class DialogNames
{
    public const string UserSettings = "YourUiNamespace.DlgUserSettings";
    public const string ProjectConfig = "CustomProjectConfigDialog";
}

二、潜在的代码异味与风险

1. 扫描逻辑的准确性隐患

  • 若对话框类未正确继承基类、或通过反射/动态类型调用RegisterDialog,生成器会漏生成常量,导致运行时抛出DialogNotFoundException
  • 自定义名称时,若生成器未正确提取注册代码中的字符串常量,会出现常量值与实际注册名称不匹配的问题

2. 跨项目耦合违反依赖倒置原则

抽象层的静态类直接依赖UI层的具体视图类型,打破了“抽象不依赖细节”的设计原则。一旦UI层类型改名、删除,抽象层会直接编译报错,增加跨项目维护成本。

3. 编译性能开销

每次编译都要扫描整个解决方案的代码,大型项目中会明显增加编译耗时;若生成器逻辑复杂,还可能出现编译卡顿。

4. 调试排查难度提升

自动生成的代码无人工编写痕迹,出现常量值错误、重复定义等问题时,需要排查生成器逻辑而非业务代码,增加调试复杂度。

5. 违背Prism的约定优于配置原则

Prism默认以视图类型的FullName作为对话框名称,完全可以通过泛型扩展方法封装ShowDialog,无需硬编码或生成静态类:

public static class DialogServiceExtensions
{
    public static void ShowDialog<TView>(this IDialogService dialogService, 
        IDialogParameters parameters = null, 
        Action<IDialogResult> callback = null)
    {
        var dialogName = typeof(TView).FullName;
        dialogService.ShowDialog(dialogName, parameters, callback);
    }
}

调用时直接写dialogService.ShowDialog<DlgUserSettings>(params),完全规避硬编码,更符合Prism的设计思路。

三、替代方案建议

  1. 泛型扩展方法封装:如上述示例,直接通过视图类型获取对话框名称,无需额外生成代码
  2. 特性统一管理名称:给对话框视图添加[DialogName("CustomAlias")]特性,在扩展方法和注册逻辑中统一读取特性值,保持名称一致性

内容的提问来源于stack exchange,提问作者Samer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 18:22:46