C# 使用Roslyn获取程序集属性
我希望能够使用Roslyn代码分析从程序集中的AssemblyInfo.cs文件中读取一些程序集属性 因此,给出以下示例:C# 使用Roslyn获取程序集属性,c#,attributes,roslyn,C#,Attributes,Roslyn,我希望能够使用Roslyn代码分析从程序集中的AssemblyInfo.cs文件中读取一些程序集属性 因此,给出以下示例: using System; using System.Collections.Generic; using System.Text; [assembly: Helloworld.TestAttribute1("Test1")] [assembly: Helloworld.TestAttribute1(TheValue = "Test1", IgnoreThis = "I
using System;
using System.Collections.Generic;
using System.Text;
[assembly: Helloworld.TestAttribute1("Test1")]
[assembly: Helloworld.TestAttribute1(TheValue = "Test1", IgnoreThis = "I dont want this one!")]
namespace Helloworld
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello, World!");
}
}
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
public class TestAttribute1 : Attribute
{
public TestAttribute1()
{
}
public TestAttribute1(string theValue)
{
this.TheValue = theValue;
}
public string TheValue { get; set; }
public string IgnoreThis { get; set; }
}
}
我希望能够提取类型为TestAttribute1
的属性和名为TheValue
的已定义属性的值
在本例中定义了两次-第一次使用构造函数参数,另一次使用命名参数
我有以下代码:
static void Main(string[] args)
{
string cs = GetFile();
SyntaxTree tree = CSharpSyntaxTree.ParseText(cs);
var root = (CompilationUnitSyntax)tree.GetRoot();
var compilation = CSharpCompilation.Create("").AddSyntaxTrees(tree);
var model = compilation.GetSemanticModel(tree);
// get the attributes
AttributeSyntax attr1 = root.DescendantNodes()
.OfType<AttributeSyntax>().ToArray()[0];
AttributeSyntax attr2 = root.DescendantNodes()
.OfType<AttributeSyntax>().ToArray()[1];
var ex1 = attr1.ArgumentList.Arguments.FirstOrDefault().Expression as LiteralExpressionSyntax;
var str1 = ex1.GetText().ToString();
var ex2 = attr2.ArgumentList.Arguments.FirstOrDefault().Expression as LiteralExpressionSyntax;
var str2 = ex2.GetText().ToString();
}
static void Main(字符串[]args)
{
字符串cs=GetFile();
SyntaxTree-tree=CSharpSyntaxTree.ParseText(cs);
var root=(CompilationUnitSyntax)tree.GetRoot();
var compilation=csharpcomilation.Create(“”).AddSyntaxTrees(树);
var model=compilation.GetSemanticModel(树);
//获取属性
AttributeSyntax attr1=root.degenantNodes()
.OfType().ToArray()[0];
AttributeSyntax attr2=root.degenantNodes()
.OfType().ToArray()[1];
var ex1=attr1.ArgumentList.Arguments.FirstOrDefault().Expression作为LiteralExpressionSyntax;
var str1=ex1.GetText().ToString();
var ex2=attr2.ArgumentList.Arguments.FirstOrDefault().Expression作为LiteralExpressionSyntax;
var str2=ex2.GetText().ToString();
}
目前我只是通过硬编码定位程序集属性来作弊。再次硬编码参数列表
,以获取其中的第一个表达式。这使我得到str1和str2的结果为\“Test1\”
是否有一种方法可以说,给我类型
TestAttribute1
的属性,然后说,给我名为TheValue
的属性的值?为了获得给定类型的属性,以下代码将起作用:
Func<AttributeSyntax, bool> findAttribute = (a) =>
{
var typeInfo = model.GetTypeInfo(a).ConvertedType;
return typeInfo.Name == "TestAttribute1" && typeInfo.ContainingNamespace.Name == "Helloworld";
};
AttributeSyntax[] attrs = root.DescendantNodes()
.OfType<AttributeSyntax>()
.Where(findAttribute)
.ToArray();
Func findAttribute=(a)=>
{
var typeInfo=model.GetTypeInfo(a).ConvertedType;
返回typeInfo.Name==“TestAttribute1”&&typeInfo.ContainingNamespace.Name==“Helloworld”;
};
AttributeSyntax[]attrs=root.degenantNodes()
第()类
.何处(findAttribute)
.ToArray();
为了获得给定类型的属性,以下代码将起作用:
Func<AttributeSyntax, bool> findAttribute = (a) =>
{
var typeInfo = model.GetTypeInfo(a).ConvertedType;
return typeInfo.Name == "TestAttribute1" && typeInfo.ContainingNamespace.Name == "Helloworld";
};
AttributeSyntax[] attrs = root.DescendantNodes()
.OfType<AttributeSyntax>()
.Where(findAttribute)
.ToArray();
Func findAttribute=(a)=>
{
var typeInfo=model.GetTypeInfo(a).ConvertedType;
返回typeInfo.Name==“TestAttribute1”&&typeInfo.ContainingNamespace.Name==“Helloworld”;
};
AttributeSyntax[]attrs=root.degenantNodes()
第()类
.何处(findAttribute)
.ToArray();
您只需尝试从IAssemblySymbol
获取属性即可实现此目的,此符号可从编译中检索:
var attribute = compilation.Assembly.GetAttributes().FirstOrDefault(x => x.AttributeClass.ToString() == "Helloworld.TestAttribute1");
if(!(attribute is null))
{
var ctorArgs = attribute.ConstructorArguments;
var propArgs = attribute.NamedArguments;
}
TypedConstant
和propArgs
是TypedConstant
项的集合(propArgs
是字典),并且TypedConstant
具有属性Value
(或Value
,当其为数组时)将传递的值保留为ctor参数或属性值。最后,您只需要使用TypedConstant.Type
筛选您感兴趣的参数
这应该如下所示:
SyntaxTree tree = CSharpSyntaxTree.ParseText(cs);
var root = (CompilationUnitSyntax)tree.GetRoot();
var compilation = CSharpCompilation.Create("test").AddSyntaxTrees(tree);
// get references to add
compilation = compilation.AddReferences(GetGlobalReferences());
var model = compilation.GetSemanticModel(tree);
var attrs = compilation.Assembly.GetAttributes().Where(x => x.AttributeClass.ToString() == "Helloworld.TestAttribute1");
foreach (var attr in attrs)
{
var ctorArgs = attr.ConstructorArguments;
var propArgs = attr.NamedArguments;
}
private静态IEnumerable GetGlobalReferences()
{
var assemblies=new[]
{
typeof(System.Object).Assembly,//mscorlib
};
var refs=来自部件中的
选择MetadataReference.CreateFromFile(a.Location);
返回refs.ToList();
}
您只需尝试从IAssemblySymbol
获取属性即可实现此目的,此符号可从编译中检索:
var attribute = compilation.Assembly.GetAttributes().FirstOrDefault(x => x.AttributeClass.ToString() == "Helloworld.TestAttribute1");
if(!(attribute is null))
{
var ctorArgs = attribute.ConstructorArguments;
var propArgs = attribute.NamedArguments;
}
TypedConstant
和propArgs
是TypedConstant
项的集合(propArgs
是字典),并且TypedConstant
具有属性Value
(或Value
,当其为数组时)将传递的值保留为ctor参数或属性值。最后,您只需要使用TypedConstant.Type
筛选您感兴趣的参数
这应该如下所示:
SyntaxTree tree = CSharpSyntaxTree.ParseText(cs);
var root = (CompilationUnitSyntax)tree.GetRoot();
var compilation = CSharpCompilation.Create("test").AddSyntaxTrees(tree);
// get references to add
compilation = compilation.AddReferences(GetGlobalReferences());
var model = compilation.GetSemanticModel(tree);
var attrs = compilation.Assembly.GetAttributes().Where(x => x.AttributeClass.ToString() == "Helloworld.TestAttribute1");
foreach (var attr in attrs)
{
var ctorArgs = attr.ConstructorArguments;
var propArgs = attr.NamedArguments;
}
private静态IEnumerable GetGlobalReferences()
{
var assemblies=new[]
{
typeof(System.Object).Assembly,//mscorlib
};
var refs=来自部件中的
选择MetadataReference.CreateFromFile(a.Location);
返回refs.ToList();
}
Hmm,出于某种原因,如果我运行属性.ConstructorArguments
和attr.NamedArguments
为空。如果我遍历而不是遍历FirstOrDefault,则这两个属性都是相同的。注意:此示例使用的是dotnetcore 2.2。@Andez,假设问题是编译不知道TestAttribute1
是属性,因为编译没有对系统库的引用:mscrolib
,system
,system.Core
。因此,如果我运行属性.ConstructorArguments
和attr.NamedArguments
为空,请尝试添加它们。如果我遍历而不是遍历FirstOrDefault,则这两个属性都是相同的。注意:此示例使用的是dotnetcore 2.2。@Andez,假设问题是编译不知道TestAttribute1
是属性,因为编译没有对系统库的引用:mscrolib
,system
,system.Core
。所以试着添加它们