【发布时间】:2021-04-07 17:51:00
【问题描述】:
我正在尝试编写一个源生成器,并且需要扩展方法调用中涉及的类型。
问题是,这个扩展方法是源码生成器自己生成的。因此,如果我尝试获取 ISymbol,我的 Generator 类中将得到 null。
是否有可能获得我需要的信息?
这是一个例子
var result = someObject.ConvertTo<OtherType>();
ConvertTo<T>() 扩展方法是从源生成器生成的。我可以找到正确的InvocationExpressionSyntax,但是如何获得someObject 和OtherType 的完全限定类型?
这里是生成器
[Generator]
public class ConvertGenerator : ISourceGenerator
{
private const string defaultNamespace = "AutoGenerators";
private const string extensionsClassName = "ConvertExtensions";
private static readonly string _classText = @$"
namespace {defaultNamespace}
{{
public static class {extensionsClassName}
{{
public static TDestination ConvertTo<TDestination>(this object source)
{{
/* generated */
return default;
}}
}} }}";
public void Initialize(GeneratorInitializationContext context)
{
#if DEBUG
if (!Debugger.IsAttached)
{
Debugger.Launch();
}
#endif
// Register a syntax receiver that will be created for each generation pass
context.RegisterForSyntaxNotifications(() => new SyntaxReceiver());
}
public void Execute(GeneratorExecutionContext context)
{
// retrieve the populated receiver
if (!(context.SyntaxReceiver is SyntaxReceiver receiver))
return;
// for testing
var invocationSyntax = receiver.Methods.FirstOrDefault();
if (invocationSyntax != null)
{
var semanticModel = context.Compilation.GetSemanticModel(invocationSyntax.SyntaxTree);
// symbol is null here
var symbol = semanticModel.GetSymbolInfo(invocationSyntax.Expression).Symbol;
// TODO: how to get type description for sourceObjectName and destinationTypeName
var convertInvocationString = invocationSyntax.ToString();
var sourceObjectName = convertInvocationString.Substring(0, convertInvocationString.IndexOf('.'));
var destTypeSubs = convertInvocationString.Substring(convertInvocationString.IndexOf('<') + 1);
var destinationTypeName = destTypeSubs.Substring(0, destTypeSubs.IndexOf('(') - 1);
}
var classSource = _classText;
context.AddSource($"{extensionsClassName}.cs", SourceText.From(classSource, Encoding.UTF8));
}
/// <summary>
/// Created on demand before each generation pass
/// </summary>
class SyntaxReceiver : ISyntaxReceiver
{
public List<InvocationExpressionSyntax> Methods { get; } = new List<InvocationExpressionSyntax>();
/// <summary>
/// Called for every syntax node in the compilation, we can inspect the nodes and save any information useful for generation
/// </summary>
public void OnVisitSyntaxNode(SyntaxNode context)
{
// any field with at least one attribute is a candidate for property generation
if (context is InvocationExpressionSyntax invocationExpressionSyntax
&& invocationExpressionSyntax.ToString().Contains("ConvertTo<"))
{
Methods.Add(invocationExpressionSyntax);
}
}
}
}
更新:我认为我需要的不仅仅是类型。我需要ISymbol 来获取类型的所有属性
更新 2:我做了一小步,将 ConvertTo<T> 方法设置为部分,并使用此方法引用分离项目。我现在得到IMethodSymbol 并且有OtherType 的ITypeSymbol,但是someObject 的ITypeSymbol 是object 类型,因为扩展方法签名。但我需要someObject 的具体类型符号
【问题讨论】:
标签: c# roslyn sourcegenerators