Skip to content

语义模型高级主题

📚 文档导航

本文档介绍语义模型的高级主题,包括泛型、继承、特性和类型转换。

📖 文档系列

文档内容难度
语义模型基础基础概念、快速入门、核心功能🟢 入门
类型信息获取GetTypeInfo、常量值、TypeInfo 详解🟡 中级
符号信息获取GetDeclaredSymbol、GetSymbolInfo、符号遍历🟡 中级
高级主题泛型、继承、特性、类型转换🔴 高级
最佳实践性能优化、常见问题、实战场景🟡 中级

泛型类型处理

泛型类和方法

csharp
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;

public class GenericTypeHandling
{
    public void DemonstrateGenerics()
    {
        var code = @"
            using System.Collections.Generic;
            
            public class Container<T>
            {
                public T Value { get; set; }
                
                public void SetValue(T value)
                {
                    Value = value;
                }
                
                public T GetValue()
                {
                    return Value;
                }
            }
            
            public class MultiGeneric<T, U> where T : class where U : struct
            {
                public T First { get; set; }
                public U Second { get; set; }
            }
            
            public class Usage
            {
                public void Test()
                {
                    var intContainer = new Container<int>();
                    var stringContainer = new Container<string>();
                    
                    var list = new List<int>();
                    var dict = new Dictionary<string, int>();
                }
            }
        ";
        
        var tree = CSharpSyntaxTree.ParseText(code);
        var compilation = CreateCompilation(tree);
        var model = compilation.GetSemanticModel(tree);
        var root = tree.GetRoot();
        
        // 1. 分析泛型类定义
        var genericClasses = root.DescendantNodes()
            .OfType<ClassDeclarationSyntax>()
            .Where(c => c.TypeParameterList != null);
        
        foreach (var classDecl in genericClasses)
        {
            var classSymbol = model.GetDeclaredSymbol(classDecl) as INamedTypeSymbol;
            
            Console.WriteLine($"泛型类: {classSymbol.Name}");
            Console.WriteLine($"  是泛型: {classSymbol.IsGenericType}");
            Console.WriteLine($"  类型参数数量: {classSymbol.TypeParameters.Length}");
            
            Console.WriteLine($"  类型参数:");
            foreach (var typeParam in classSymbol.TypeParameters)
            {
                Console.WriteLine($"    - {typeParam.Name}");
                Console.WriteLine($"      有引用类型约束: {typeParam.HasReferenceTypeConstraint}");
                Console.WriteLine($"      有值类型约束: {typeParam.HasValueTypeConstraint}");
                Console.WriteLine($"      有构造函数约束: {typeParam.HasConstructorConstraint}");
                
                if (typeParam.ConstraintTypes.Any())
                {
                    Console.WriteLine($"      类型约束:");
                    foreach (var constraint in typeParam.ConstraintTypes)
                    {
                        Console.WriteLine($"        - {constraint.ToDisplayString()}");
                    }
                }
            }
            Console.WriteLine();
        }
        
        // 2. 分析泛型类型的使用
        var objectCreations = root.DescendantNodes()
            .OfType<ObjectCreationExpressionSyntax>();
        
        foreach (var creation in objectCreations)
        {
            var typeInfo = model.GetTypeInfo(creation);
            var type = typeInfo.Type as INamedTypeSymbol;
            
            if (type != null && type.IsGenericType)
            {
                Console.WriteLine($"泛型类型实例: {creation.Type}");
                Console.WriteLine($"  完整类型: {type.ToDisplayString()}");
                Console.WriteLine($"  原始定义: {type.OriginalDefinition.ToDisplayString()}");
                Console.WriteLine($"  是构造的泛型类型: {type.IsGenericType && !type.IsUnboundGenericType}");
                
                Console.WriteLine($"  类型参数:");
                foreach (var typeArg in type.TypeArguments)
                {
                    Console.WriteLine($"    - {typeArg.ToDisplayString()}");
                    Console.WriteLine($"      种类: {typeArg.TypeKind}");
                    Console.WriteLine($"      是值类型: {typeArg.IsValueType}");
                    Console.WriteLine($"      是引用类型: {typeArg.IsReferenceType}");
                }
                Console.WriteLine();
            }
        }
    }
    
    private Compilation CreateCompilation(SyntaxTree tree)
    {
        return CSharpCompilation.Create("temp")
            .AddReferences(
                MetadataReference.CreateFromFile(typeof(object).Assembly.Location),
                MetadataReference.CreateFromFile(typeof(List<>).Assembly.Location)
            )
            .AddSyntaxTrees(tree);
    }
}

💡 泛型类型关键概念

  • IsGenericType: 是否是泛型类型
  • TypeParameters: 类型参数(定义时)
  • TypeArguments: 类型参数(使用时)
  • OriginalDefinition: 原始泛型定义

泛型类型实用工具

csharp
public static class GenericTypeHelpers
{
    // 检查类型是否是特定泛型类型的实例
    public static bool IsGenericTypeOf(ITypeSymbol type, string genericTypeName)
    {
        if (type is INamedTypeSymbol namedType && namedType.IsGenericType)
        {
            var originalDefinition = namedType.OriginalDefinition.ToDisplayString();
            return originalDefinition.StartsWith(genericTypeName + "<");
        }
        return false;
    }
    
    // 获取泛型类型参数
    public static ITypeSymbol[] GetGenericArguments(ITypeSymbol type)
    {
        if (type is INamedTypeSymbol namedType && namedType.IsGenericType)
        {
            return namedType.TypeArguments.ToArray();
        }
        return Array.Empty<ITypeSymbol>();
    }
    
    // 检查是否是 List<T>
    public static bool IsList(ITypeSymbol type)
    {
        return IsGenericTypeOf(type, "System.Collections.Generic.List");
    }
    
    // 检查是否是 Dictionary<TKey, TValue>
    public static bool IsDictionary(ITypeSymbol type)
    {
        return IsGenericTypeOf(type, "System.Collections.Generic.Dictionary");
    }
    
    // 获取 List<T> 的元素类型
    public static ITypeSymbol GetListElementType(ITypeSymbol type)
    {
        if (IsList(type))
        {
            var args = GetGenericArguments(type);
            return args.Length > 0 ? args[0] : null;
        }
        return null;
    }
}

继承和接口分析

分析类型层次结构

csharp
public class InheritanceAnalysis
{
    public void AnalyzeHierarchy()
    {
        var code = @"
            interface IAnimal { void MakeSound(); }
            interface IMammal : IAnimal { void Feed(); }
            
            abstract class Animal : IAnimal
            {
                public abstract void MakeSound();
            }
            
            class Dog : Animal, IMammal
            {
                public override void MakeSound() { }
                public void Feed() { }
            }
            
            class GermanShepherd : Dog { }
        ";
        
        var tree = CSharpSyntaxTree.ParseText(code);
        var compilation = CreateCompilation(tree);
        var model = compilation.GetSemanticModel(tree);
        var root = tree.GetRoot();
        
        var germanShepherd = root.DescendantNodes()
            .OfType<ClassDeclarationSyntax>()
            .First(c => c.Identifier.Text == "GermanShepherd");
        
        var symbol = model.GetDeclaredSymbol(germanShepherd) as INamedTypeSymbol;
        
        Console.WriteLine($"类: {symbol.Name}");
        Console.WriteLine($"\n继承链:");
        var current = symbol;
        while (current != null)
        {
            Console.WriteLine($"  - {current.ToDisplayString()}");
            current = current.BaseType;
        }
        
        Console.WriteLine($"\n实现的接口:");
        foreach (var iface in symbol.AllInterfaces)
        {
            Console.WriteLine($"  - {iface.ToDisplayString()}");
        }
        
        Console.WriteLine($"\n所有成员:");
        foreach (var member in symbol.GetMembers())
        {
            Console.WriteLine($"  - {member.ToDisplayString()}");
        }
    }
    
    private Compilation CreateCompilation(SyntaxTree tree)
    {
        return CSharpCompilation.Create("temp")
            .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location))
            .AddSyntaxTrees(tree);
    }
}

继承关系检查工具

csharp
public static class InheritanceHelpers
{
    // 检查是否继承自特定类
    public static bool InheritsFrom(ITypeSymbol derived, ITypeSymbol baseType)
    {
        var current = derived.BaseType;
        while (current != null)
        {
            if (SymbolEqualityComparer.Default.Equals(current, baseType))
            {
                return true;
            }
            current = current.BaseType;
        }
        return false;
    }
    
    // 检查是否实现特定接口
    public static bool ImplementsInterface(ITypeSymbol type, ITypeSymbol interfaceType)
    {
        return type.AllInterfaces.Any(i => 
            SymbolEqualityComparer.Default.Equals(i, interfaceType));
    }
    
    // 检查是否实现特定接口(按名称)
    public static bool ImplementsInterface(ITypeSymbol type, string interfaceName)
    {
        return type.AllInterfaces.Any(i => 
            i.ToDisplayString() == interfaceName);
    }
    
    // 获取所有基类
    public static IEnumerable<INamedTypeSymbol> GetBaseTypes(ITypeSymbol type)
    {
        var current = type.BaseType;
        while (current != null)
        {
            yield return current;
            current = current.BaseType;
        }
    }
    
    // 获取类型层次深度
    public static int GetInheritanceDepth(ITypeSymbol type)
    {
        int depth = 0;
        var current = type.BaseType;
        while (current != null)
        {
            depth++;
            current = current.BaseType;
        }
        return depth;
    }
}

特性(Attribute)处理

获取和分析特性

csharp
public class AttributeHandling
{
    public void DemonstrateAttributes()
    {
        var code = @"
            using System;
            using System.ComponentModel;
            
            [Serializable]
            [Description(""This is a person class"")]
            public class Person
            {
                [Required]
                [MaxLength(100)]
                public string Name { get; set; }
                
                [Range(0, 150)]
                public int Age { get; set; }
                
                [Obsolete(""Use NewMethod instead"", false)]
                public void OldMethod() { }
                
                public void NewMethod() { }
            }
            
            // 自定义特性
            [AttributeUsage(AttributeTargets.Property)]
            public class RequiredAttribute : Attribute { }
            
            [AttributeUsage(AttributeTargets.Property)]
            public class MaxLengthAttribute : Attribute
            {
                public int Length { get; }
                public MaxLengthAttribute(int length) { Length = length; }
            }
            
            [AttributeUsage(AttributeTargets.Property)]
            public class RangeAttribute : Attribute
            {
                public int Min { get; }
                public int Max { get; }
                public RangeAttribute(int min, int max) 
                { 
                    Min = min; 
                    Max = max; 
                }
            }
        ";
        
        var tree = CSharpSyntaxTree.ParseText(code);
        var compilation = CreateCompilation(tree);
        var model = compilation.GetSemanticModel(tree);
        var root = tree.GetRoot();
        
        // 1. 获取类的特性
        var classDecl = root.DescendantNodes()
            .OfType<ClassDeclarationSyntax>()
            .First(c => c.Identifier.Text == "Person");
        
        var classSymbol = model.GetDeclaredSymbol(classDecl) as INamedTypeSymbol;
        
        Console.WriteLine($"类: {classSymbol.Name}");
        Console.WriteLine($"特性:");
        
        foreach (var attribute in classSymbol.GetAttributes())
        {
            Console.WriteLine($"  [{attribute.AttributeClass.Name}]");
            
            // 获取构造函数参数
            if (attribute.ConstructorArguments.Any())
            {
                Console.WriteLine($"    构造函数参数:");
                foreach (var arg in attribute.ConstructorArguments)
                {
                    Console.WriteLine($"      - {arg.Type.ToDisplayString()}: {arg.Value}");
                }
            }
            
            // 获取命名参数
            if (attribute.NamedArguments.Any())
            {
                Console.WriteLine($"    命名参数:");
                foreach (var arg in attribute.NamedArguments)
                {
                    Console.WriteLine($"      - {arg.Key} = {arg.Value.Value}");
                }
            }
        }
        Console.WriteLine();
        
        // 2. 获取属性的特性
        var properties = root.DescendantNodes()
            .OfType<PropertyDeclarationSyntax>();
        
        foreach (var property in properties)
        {
            var propertySymbol = model.GetDeclaredSymbol(property) as IPropertySymbol;
            
            if (propertySymbol.GetAttributes().Any())
            {
                Console.WriteLine($"属性: {propertySymbol.Name}");
                Console.WriteLine($"特性:");
                
                foreach (var attribute in propertySymbol.GetAttributes())
                {
                    Console.WriteLine($"  [{attribute.AttributeClass.Name}]");
                    
                    if (attribute.ConstructorArguments.Any())
                    {
                        Console.WriteLine($"    参数:");
                        foreach (var arg in attribute.ConstructorArguments)
                        {
                            Console.WriteLine($"      - {arg.Value}");
                        }
                    }
                }
                Console.WriteLine();
            }
        }
    }
    
    private Compilation CreateCompilation(SyntaxTree tree)
    {
        return CSharpCompilation.Create("temp")
            .AddReferences(
                MetadataReference.CreateFromFile(typeof(object).Assembly.Location),
                MetadataReference.CreateFromFile(typeof(SerializableAttribute).Assembly.Location),
                MetadataReference.CreateFromFile(typeof(DescriptionAttribute).Assembly.Location),
                MetadataReference.CreateFromFile(typeof(ObsoleteAttribute).Assembly.Location)
            )
            .AddSyntaxTrees(tree);
    }
}

特性处理工具

csharp
public static class AttributeHelpers
{
    // 检查符号是否有特定特性
    public static bool HasAttribute(ISymbol symbol, string attributeName)
    {
        return symbol.GetAttributes()
            .Any(a => a.AttributeClass?.Name == attributeName ||
                     a.AttributeClass?.ToDisplayString() == attributeName);
    }
    
    // 获取特定特性
    public static AttributeData GetAttribute(ISymbol symbol, string attributeName)
    {
        return symbol.GetAttributes()
            .FirstOrDefault(a => a.AttributeClass?.Name == attributeName ||
                                a.AttributeClass?.ToDisplayString() == attributeName);
    }
    
    // 获取特性的构造函数参数值
    public static T GetAttributeArgument<T>(AttributeData attribute, int index, T defaultValue = default)
    {
        if (attribute.ConstructorArguments.Length > index)
        {
            var arg = attribute.ConstructorArguments[index];
            if (arg.Value is T value)
            {
                return value;
            }
        }
        return defaultValue;
    }
    
    // 获取特性的命名参数值
    public static T GetAttributeNamedArgument<T>(AttributeData attribute, string name, T defaultValue = default)
    {
        var namedArg = attribute.NamedArguments
            .FirstOrDefault(a => a.Key == name);
        
        if (namedArg.Value.Value is T value)
        {
            return value;
        }
        
        return defaultValue;
    }
    
    // 检查是否有 Obsolete 特性
    public static bool IsObsolete(ISymbol symbol)
    {
        return HasAttribute(symbol, "ObsoleteAttribute");
    }
    
    // 获取 Obsolete 消息
    public static string GetObsoleteMessage(ISymbol symbol)
    {
        var attr = GetAttribute(symbol, "ObsoleteAttribute");
        return attr != null ? GetAttributeArgument<string>(attr, 0, "") : null;
    }
}

类型转换和兼容性

ClassifyConversion 方法

csharp
public class ConversionExamples
{
    public void DemonstrateConversions()
    {
        var code = @"
            class Base { }
            class Derived : Base { }
            
            interface IExample { }
            class Implementation : IExample { }
            
            class ConversionTests
            {
                public void Test()
                {
                    // 值类型转换
                    int i = 5;
                    long l = i;  // 隐式转换
                    
                    // 引用类型转换
                    Derived d = new Derived();
                    Base b = d;  // 隐式向上转换
                    
                    // 接口转换
                    Implementation impl = new Implementation();
                    IExample iface = impl;  // 隐式转换
                    
                    // 显式转换
                    object obj = ""hello"";
                    string str = (string)obj;
                }
            }
        ";
        
        var tree = CSharpSyntaxTree.ParseText(code);
        var compilation = CreateCompilation(tree);
        var model = compilation.GetSemanticModel(tree);
        var root = tree.GetRoot();
        
        // 分析所有赋值语句的转换
        var assignments = root.DescendantNodes()
            .OfType<AssignmentExpressionSyntax>()
            .Where(a => a.IsKind(SyntaxKind.SimpleAssignmentExpression));
        
        foreach (var assignment in assignments)
        {
            var leftType = model.GetTypeInfo(assignment.Left).Type;
            var rightType = model.GetTypeInfo(assignment.Right).Type;
            
            if (leftType != null && rightType != null)
            {
                var conversion = model.ClassifyConversion(assignment.Right, leftType);
                
                Console.WriteLine($"赋值: {assignment}");
                Console.WriteLine($"  源类型: {rightType.ToDisplayString()}");
                Console.WriteLine($"  目标类型: {leftType.ToDisplayString()}");
                Console.WriteLine($"  转换存在: {conversion.Exists}");
                Console.WriteLine($"  是恒等转换: {conversion.IsIdentity}");
                Console.WriteLine($"  是隐式转换: {conversion.IsImplicit}");
                Console.WriteLine($"  是显式转换: {conversion.IsExplicit}");
                Console.WriteLine($"  是引用转换: {conversion.IsReference}");
                Console.WriteLine($"  是数值转换: {conversion.IsNumeric}");
                Console.WriteLine($"  是装箱转换: {conversion.IsBoxing}");
                Console.WriteLine($"  是拆箱转换: {conversion.IsUnboxing}");
                Console.WriteLine();
            }
        }
    }
    
    private Compilation CreateCompilation(SyntaxTree tree)
    {
        return CSharpCompilation.Create("temp")
            .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location))
            .AddSyntaxTrees(tree);
    }
}

转换检查工具

csharp
public static class ConversionHelpers
{
    // 检查类型兼容性
    public static bool CanConvert(
        SemanticModel model, 
        ExpressionSyntax expression, 
        ITypeSymbol targetType)
    {
        var conversion = model.ClassifyConversion(expression, targetType);
        return conversion.Exists;
    }
    
    // 检查是否可以隐式转换
    public static bool CanImplicitlyConvert(
        SemanticModel model, 
        ExpressionSyntax expression, 
        ITypeSymbol targetType)
    {
        var conversion = model.ClassifyConversion(expression, targetType);
        return conversion.IsImplicit;
    }
    
    // 检查是否需要显式转换
    public static bool RequiresExplicitConversion(
        SemanticModel model, 
        ExpressionSyntax expression, 
        ITypeSymbol targetType)
    {
        var conversion = model.ClassifyConversion(expression, targetType);
        return conversion.Exists && conversion.IsExplicit && !conversion.IsImplicit;
    }
    
    // 检查是否是装箱转换
    public static bool IsBoxingConversion(
        SemanticModel model, 
        ExpressionSyntax expression, 
        ITypeSymbol targetType)
    {
        var conversion = model.ClassifyConversion(expression, targetType);
        return conversion.IsBoxing;
    }
    
    // 检查是否是拆箱转换
    public static bool IsUnboxingConversion(
        SemanticModel model, 
        ExpressionSyntax expression, 
        ITypeSymbol targetType)
    {
        var conversion = model.ClassifyConversion(expression, targetType);
        return conversion.IsUnboxing;
    }
}

💡 转换类型

  • IsIdentity: 恒等转换(相同类型)
  • IsImplicit: 隐式转换(自动)
  • IsExplicit: 显式转换(需要强制转换)
  • IsReference: 引用转换
  • IsNumeric: 数值转换
  • IsBoxing: 装箱转换
  • IsUnboxing: 拆箱转换

下一步


🔗 相关资源


最后更新: 2025-01-21

基于 MIT 许可发布