我有一个来自罗斯林语法树的ClassDeclarationSyntax。我是这样读的:
var tree = SyntaxTree.ParseText(sourceCode);
var root = (CompilationUnitSyntax)tree.GetRoot();
var classes = root.DescendantNodes().OfType<ClassDeclarationSyntax>();标识符只包含类的名称,但不包含有关名称空间的信息,因此缺少fullType名称。像"MyClass“,但不是"Namespace1.MyClass”
获取语法的名称空间/ FulltypeName的推荐方法是什么?
发布于 2014-04-23 23:33:54
您可以使用我编写的helper类来完成此操作:
NamespaceDeclarationSyntax namespaceDeclarationSyntax = null;
if (!SyntaxNodeHelper.TryGetParentSyntax(classDeclarationSyntax, out namespaceDeclarationSyntax))
{
return; // or whatever you want to do in this scenario
}
var namespaceName = namespaceDeclarationSyntax.Name.ToString();
var fullClassName = namespaceName + "." + classDeclarationSyntax.Identifier.ToString();帮助者:
static class SyntaxNodeHelper
{
public static bool TryGetParentSyntax<T>(SyntaxNode syntaxNode, out T result)
where T : SyntaxNode
{
// set defaults
result = null;
if (syntaxNode == null)
{
return false;
}
try
{
syntaxNode = syntaxNode.Parent;
if (syntaxNode == null)
{
return false;
}
if (syntaxNode.GetType() == typeof (T))
{
result = syntaxNode as T;
return true;
}
return TryGetParentSyntax<T>(syntaxNode, out result);
}
catch
{
return false;
}
}
}这里并没有什么太复杂的事情。名称空间在语法树中“向上”是有意义的(因为类包含在名称空间中),所以您只需要在语法树中“向上”移动,直到找到名称空间,并将其附加到ClassDeclarationSyntax的标识符。
发布于 2018-10-08 11:24:46
我知道我在游戏中相当晚,但我偶然发现了one of given the answers,它在我不得不处理嵌套类的情况下不起作用。因此,下面是一个处理嵌套类的方法:
public static class ClassDeclarationSyntaxExtensions
{
public const string NESTED_CLASS_DELIMITER = "+";
public const string NAMESPACE_CLASS_DELIMITER = ".";
public static string GetFullName(this ClassDeclarationSyntax source)
{
Contract.Requires(null != source);
var items = new List<string>();
var parent = source.Parent;
while (parent.IsKind(SyntaxKind.ClassDeclaration))
{
var parentClass = parent as ClassDeclarationSyntax;
Contract.Assert(null != parentClass);
items.Add(parentClass.Identifier.Text);
parent = parent.Parent;
}
var nameSpace = parent as NamespaceDeclarationSyntax;
Contract.Assert(null != nameSpace);
var sb = new StringBuilder().Append(nameSpace.Name).Append(NAMESPACE_CLASS_DELIMITER);
items.Reverse();
items.ForEach(i => { sb.Append(i).Append(NESTED_CLASS_DELIMITER); });
sb.Append(source.Identifier.Text);
var result = sb.ToString();
return result;
}
}发布于 2020-04-24 21:22:12
基于the answer by Ronald,我添加了对:嵌套名称空间、结构和泛型的支持。
它使用generics CLR naming convention来允许将输出用作Compilation.GetTypeByMetadataName()的输入
public static class TypeDeclarationSyntaxExtensions
{
const char NESTED_CLASS_DELIMITER = '+';
const char NAMESPACE_CLASS_DELIMITER = '.';
const char TYPEPARAMETER_CLASS_DELIMITER = '`';
public static string GetFullName(this TypeDeclarationSyntax source)
{
if (source is null)
throw new ArgumentNullException(nameof(source));
var namespaces = new LinkedList<NamespaceDeclarationSyntax>();
var types = new LinkedList<TypeDeclarationSyntax>();
for (var parent = source.Parent; parent is object; parent = parent.Parent)
{
if (parent is NamespaceDeclarationSyntax @namespace)
{
namespaces.AddFirst(@namespace);
}
else if (parent is TypeDeclarationSyntax type)
{
types.AddFirst(type);
}
}
var result = new StringBuilder();
for (var item = namespaces.First; item is object; item = item.Next)
{
result.Append(item.Value.Name).Append(NAMESPACE_CLASS_DELIMITER);
}
for (var item = types.First; item is object; item = item.Next)
{
var type = item.Value;
AppendName(result, type);
result.Append(NESTED_CLASS_DELIMITER);
}
AppendName(result, source);
return result.ToString();
}
static void AppendName(StringBuilder builder, TypeDeclarationSyntax type)
{
builder.Append(type.Identifier.Text);
var typeArguments = type.TypeParameterList?.ChildNodes()
.Count(node => node is TypeParameterSyntax) ?? 0;
if (typeArguments != 0)
builder.Append(TYPEPARAMETER_CLASS_DELIMITER).Append(typeArguments);
}
}https://stackoverflow.com/questions/20458457
复制相似问题