我几天前开始和roslyn一起玩,我正在尝试编写一个扩展方法,告诉public static bool HasBackingField(this IPropertySymbol property)
{
return !(property.IsAbstract || property.IsExtern || property.IsReadOnly);
}
是否有一个支持字段,所以我认为一个属性有一个支持字段,当且仅当以下情况不适用(据我所知):
所以我想出了
GetMethod
我的问题是
SetMethod
中找到了IPropertySymbol
和 var code =
@"class XYZ
{
public int x => 4; //HasBacking field : false IsReadOnly
public int m { get { return 0;}} //HasBacking field : false IsReadOnly
public int y { get; set; } //HasBacking field : false Null body for setter or getter
public int z { get { return 0; } set { } } //HasBacking field : false Empty body for setter or getter
private int _g;
public int g //HasBacking field : true Getter and Setter has no empty Bodies
{
get { return _g; }
set { _g = value; }
}
}";
var syntaxTree = CSharpSyntaxTree.ParseText(code);
var compilation = CSharpCompilation.Create("xxx").AddSyntaxTrees(syntaxTree);
var classSymbol = compilation.GetTypeByMetadataName("XYZ");
var propSymbols = classSymbol.GetMembers().OfType<IPropertySymbol>();
var results = propSymbols.Select(ps => ps.HasBackingField()); //should be [false false false false true]
属性,但我不知道检查他们是否有身体启动
的示例 A SQLiteConnection object for database '//data//data//com.compapps.booster//databases//booster.db' was leaked! Please fix your application to end transactions in progress properly and to close the database when it is no longer needed.
答案 0 :(得分:2)
我决定查看语法表示而不是实际符号 - 语法位于比符号更低的级别,并包含我们感兴趣的原始信息:查看单个语句。
这似乎做了你感兴趣的事情:
internal static bool HasBackingField(this PropertyDeclarationSyntax property)
{
var getter = property.AccessorList?.Accessors.FirstOrDefault(x => x.IsKind(SyntaxKind.GetAccessorDeclaration));
var setter = property.AccessorList?.Accessors.FirstOrDefault(x => x.IsKind(SyntaxKind.SetAccessorDeclaration));
if (setter?.Body == null || getter?.Body == null)
{
return false;
}
bool setterHasBodyStatements = setter.Body.Statements.Any();
bool getterHasBodyStatements = getter.Body.Statements.Any();
return setterHasBodyStatements && getterHasBodyStatements;
}
请注意,我不相信这是足够可靠的,可以得出结论,有一个支持字段可用,但它遵循你通过检查是否有身体的想法。
我没有添加您考虑过的其他检查,但这些检查可以简单地添加(使用您已经做过的符号或查看PropertyDeclarationSyntax
其修饰符/属性)。
完整代码自行测试:
public static void Execute()
{
var code =
@"class XYZ
{
public int x => 4; //HasBacking field : false IsReadOnly
public int m { get { return 0;}} //HasBacking field : false IsReadOnly
public int y { get; set; } //HasBacking field : false Null body for setter or getter
public int z { get { return 0; } set { } } //HasBacking field : false Empty body for setter or getter
private int _g;
public int g //HasBacking field : true Getter and Setter has no empty Bodies
{
get { return _g; }
set { _g = value; }
}
}";
var tree = CSharpSyntaxTree.ParseText(code);
var root = tree.GetRoot();
foreach (var prop in root.DescendantNodes().OfType<PropertyDeclarationSyntax>())
{
Console.WriteLine(prop.HasBackingField());
}
}
}
internal static class Extensions
{
internal static bool HasBackingField(this PropertyDeclarationSyntax property)
{
var getter = property.AccessorList?.Accessors.FirstOrDefault(x => x.IsKind(SyntaxKind.GetAccessorDeclaration));
var setter = property.AccessorList?.Accessors.FirstOrDefault(x => x.IsKind(SyntaxKind.SetAccessorDeclaration));
if (setter?.Body == null || getter?.Body == null)
{
return false;
}
bool setterHasBodyStatements = setter.Body.Statements.Any();
bool getterHasBodyStatements = getter.Body.Statements.Any();
return setterHasBodyStatements && getterHasBodyStatements;
}
}