在Roslyn分析器中如何从TypeSymbol获取System.Type实例
Roslyn 诊断分析器实例化校验方案
核心结论
无法直接从INamedTypeSymbol获取运行时System.Type实例。
INamedTypeSymbol是Roslyn针对编译期代码符号的抽象对象,此时你要校验的类还处于编译阶段,尚未被编译为程序集加载到当前分析器的运行时环境中,自然不存在对应的运行时System.Type实例,因此也无法直接传入Activator.CreateInstance方法。
替代方案:编译期直接完成可实例化校验
你完全不需要调用运行时的Activator.CreateInstance做校验,通过INamedTypeSymbol的内置属性即可完成所有实例化前置条件检查,覆盖所有Activator.CreateInstance会抛出异常的场景:
- 检查类不是抽象类:
type.IsAbstract返回false - 检查类不是静态类:
type.IsStatic返回false - 检查存在可访问的公共无参构造函数:遍历
type.Constructors集合,存在符合以下条件的构造函数即可:constructor.DeclaredAccessibility == Accessibility.Public && constructor.Parameters.Length == 0 && !constructor.IsStatic - 若为泛型类:额外检查你传入的泛型参数满足
type.TypeParameters中定义的所有约束条件即可。
特殊场景必须获取System.Type的处理方式
如果你确实有业务要求必须调用Activator.CreateInstance拿到实例,需要走以下流程:
- 调用当前编译上下文的
Compilation.Emit方法,将整个项目编译输出为程序集文件/内存流 - 用
Assembly.Load(流/文件路径)将编译好的程序集加载到当前运行时上下文 - 通过
type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)拿到类的完全限定名,调用加载后的程序集的GetType(完全限定名)方法拿到对应的System.Type实例 - 将拿到的
Type传入Activator.CreateInstance即可完成实例化。
内容的提问来源于stack exchange,提问作者mseth
相关产品推荐
相关产品推荐

