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

如何在Roslyn中基于INamedTypeSymbol构造System.Action<>泛型类型

如何将INamedTypeSymbol包装为System.Action<>泛型类型符号

要在Roslyn中把一个INamedTypeSymbol(比如MyAwesomeApp.Foo)转换为对应的System.Action<MyAwesomeApp.Foo>类型符号,核心是通过编译上下文获取Action的泛型定义,再用目标类型构造具体泛型实例,具体实现如下:

实现步骤

  • 获取编译上下文:从目标类型符号的所在程序集拿到Compilation对象,这是访问系统类型的唯一可靠入口。
  • 获取Action的泛型定义:通过元数据名称System.Action1获取未构造的Action<>`泛型类型符号。
  • 构造具体泛型类型:调用泛型定义的Construct方法,传入目标类型符号,得到最终的Action<T>类型符号。

代码示例

using Microsoft.CodeAnalysis;
using System;

public static class SymbolExtensions
{
    public static INamedTypeSymbol ToActionOfType(this INamedTypeSymbol targetType)
    {
        if (targetType == null)
            throw new ArgumentNullException(nameof(targetType));

        // 获取当前编译环境
        Compilation compilation = targetType.ContainingAssembly.Compilation;

        // 获取System.Action<T>的泛型定义,元数据名称格式为"类型全名`泛型参数数量"
        INamedTypeSymbol actionGenericDef = compilation.GetTypeByMetadataName("System.Action`1") 
            ?? throw new InvalidOperationException("无法在当前编译环境中找到System.Action<T>类型");

        // 构造具体的Action<目标类型>
        return actionGenericDef.Construct(targetType);
    }
}

关键说明

  • 元数据名称规则:泛型类型的元数据名称格式是类型全名泛型参数数量,比如Action<T1,T2>对应System.Action2,以此类推。
  • 编译上下文的必要性:必须通过当前Compilation获取类型,避免跨编译环境的类型不匹配问题。
  • 多参数Action扩展:如果需要构造多参数的Action,只需修改元数据名称并传入多个类型符号即可,示例:
    // 获取Action<T1,T2>的泛型定义
    INamedTypeSymbol action2GenericDef = compilation.GetTypeByMetadataName("System.Action`2");
    // 构造Action<Foo, Bar>
    INamedTypeSymbol actionOfFooBar = action2GenericDef.Construct(fooTypeSymbol, barTypeSymbol);
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 23:55:17