如何在自定义 FxCop 规则中检测自动实施的 属性?
How to detect an auto-implemented property in a custom FxCop rule?
我正在尝试为 DTO 编写一条规则,它只允许自动实现的属性。您如何检测 属性 是使用 FxCop API 自动实现的?
实际上,自动属性和用户在 IL 编译代码中实现的属性是有区别的。自动属性 setter 和 getter 标记为 System.Runtime.CompilerServices.CompilerGeneratedAttribute.
因此使用 NDepend 工具,where you can write custom code queries and custom code rules through C# LINQ queries,匹配自动属性 getter 和 setter 只是编写 LINQ 查询的问题:
from m in Application.Methods
where (m.IsPropertyGetter|| m.IsPropertySetter)
&& m.IsGeneratedByCompiler
select m
请注意,在上面的屏幕截图中,您可能会匹配 Resources
中生成的 类 中的 getter 和 setter,为防止这种情况,您可以添加一个子句,例如 && !m.ParentType.IsUsing("System.Resources.ResourceManager")
:
当然,这一切都可以适配FxCop自定义裁定系统。
免责声明:我为 NDepend
工作
谢谢来自 NDepend 团队的@Patrick。这是生成的 FxCop 规则的代码。
using Microsoft.FxCop.Sdk;
using System.Linq;
using System.Runtime.CompilerServices;
namespace CustomFxRules
{
internal sealed class IsAutoImplementedProperty : BaseIntrospectionRule
{
public IsAutoImplementedProperty()
: base("IsAutoImplementedProperty", "CustomFxRules.CustomFxRules", typeof(IsAutoImplementedProperty).Assembly)
{
}
public override TargetVisibilities TargetVisibility
{
get { return TargetVisibilities.ExternallyVisible; }
}
private TypeNode CompilerGeneratedAttributeType { get; set; }
public override void BeforeAnalysis()
{
base.BeforeAnalysis();
this.CompilerGeneratedAttributeType = FrameworkAssemblies.Mscorlib.GetType(
Identifier.For("System.Reflection"),
Identifier.For("CompilerGeneratedAttribute"));
}
public override ProblemCollection Check(Member member)
{
if (member.NodeType != NodeType.Property)
return base.Check(member);
var property = (PropertyNode)member;
VisitProperty(property);
return this.Problems;
}
private const string AddAutoImplementedPropertyResolutionName = "Add auto-implemented property";
public override void VisitProperty(PropertyNode property)
{
if (property.Getter == null)
{
Problems.Add(new Problem(new Resolution(AddAutoImplementedPropertyResolutionName, "{0} property must have a getter", property.FullName)));
}
else if (property.Getter.Attributes.All(attributeNode => attributeNode.Type.FullName != typeof(CompilerGeneratedAttribute).FullName))
{
Problems.Add(new Problem(new Resolution(AddAutoImplementedPropertyResolutionName, "{0} property must have an auto-impelemented getter", property.FullName)));
}
if (property.Setter == null)
{
Problems.Add(new Problem(new Resolution(AddAutoImplementedPropertyResolutionName, "{0} property must have a setter", property.FullName)));
}
else if (property.Setter.Attributes.All(attributeNode => attributeNode.Type.FullName != typeof(CompilerGeneratedAttribute).FullName))
{
Problems.Add(new Problem(new Resolution(AddAutoImplementedPropertyResolutionName, "{0} property must have an auto-impelemented setter", property.FullName)));
}
}
}
}
我正在尝试为 DTO 编写一条规则,它只允许自动实现的属性。您如何检测 属性 是使用 FxCop API 自动实现的?
实际上,自动属性和用户在 IL 编译代码中实现的属性是有区别的。自动属性 setter 和 getter 标记为 System.Runtime.CompilerServices.CompilerGeneratedAttribute.
因此使用 NDepend 工具,where you can write custom code queries and custom code rules through C# LINQ queries,匹配自动属性 getter 和 setter 只是编写 LINQ 查询的问题:
from m in Application.Methods
where (m.IsPropertyGetter|| m.IsPropertySetter)
&& m.IsGeneratedByCompiler
select m
请注意,在上面的屏幕截图中,您可能会匹配 Resources
中生成的 类 中的 getter 和 setter,为防止这种情况,您可以添加一个子句,例如 && !m.ParentType.IsUsing("System.Resources.ResourceManager")
:
当然,这一切都可以适配FxCop自定义裁定系统。
免责声明:我为 NDepend
工作谢谢来自 NDepend 团队的@Patrick。这是生成的 FxCop 规则的代码。
using Microsoft.FxCop.Sdk;
using System.Linq;
using System.Runtime.CompilerServices;
namespace CustomFxRules
{
internal sealed class IsAutoImplementedProperty : BaseIntrospectionRule
{
public IsAutoImplementedProperty()
: base("IsAutoImplementedProperty", "CustomFxRules.CustomFxRules", typeof(IsAutoImplementedProperty).Assembly)
{
}
public override TargetVisibilities TargetVisibility
{
get { return TargetVisibilities.ExternallyVisible; }
}
private TypeNode CompilerGeneratedAttributeType { get; set; }
public override void BeforeAnalysis()
{
base.BeforeAnalysis();
this.CompilerGeneratedAttributeType = FrameworkAssemblies.Mscorlib.GetType(
Identifier.For("System.Reflection"),
Identifier.For("CompilerGeneratedAttribute"));
}
public override ProblemCollection Check(Member member)
{
if (member.NodeType != NodeType.Property)
return base.Check(member);
var property = (PropertyNode)member;
VisitProperty(property);
return this.Problems;
}
private const string AddAutoImplementedPropertyResolutionName = "Add auto-implemented property";
public override void VisitProperty(PropertyNode property)
{
if (property.Getter == null)
{
Problems.Add(new Problem(new Resolution(AddAutoImplementedPropertyResolutionName, "{0} property must have a getter", property.FullName)));
}
else if (property.Getter.Attributes.All(attributeNode => attributeNode.Type.FullName != typeof(CompilerGeneratedAttribute).FullName))
{
Problems.Add(new Problem(new Resolution(AddAutoImplementedPropertyResolutionName, "{0} property must have an auto-impelemented getter", property.FullName)));
}
if (property.Setter == null)
{
Problems.Add(new Problem(new Resolution(AddAutoImplementedPropertyResolutionName, "{0} property must have a setter", property.FullName)));
}
else if (property.Setter.Attributes.All(attributeNode => attributeNode.Type.FullName != typeof(CompilerGeneratedAttribute).FullName))
{
Problems.Add(new Problem(new Resolution(AddAutoImplementedPropertyResolutionName, "{0} property must have an auto-impelemented setter", property.FullName)));
}
}
}
}