I'm trying to write a rule for DTOs, that only allows auto-implemented properties. How do you detect that a property is auto-implemented using the FxCop API?
How to detect an auto-implemented property in a custom FxCop rule?
147 views Asked by Roman Dvoskin At
2
There are 2 answers
0
On
Thank you @Patrick from NDepend team. Here's the code for the resulting FxCop rule.
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)));
}
}
}
}
Actually there is a difference between auto-properties and properties implemented by user in the IL compiled code. Auto-properties setters and getters are tagged with System.Runtime.CompilerServices.CompilerGeneratedAttribute.
Hence with the tool NDepend, where you can write custom code queries and custom code rules through C# LINQ queries, matching auto-properties getters and setters is just a matter of writing the LINQ query:
Notice in the screenshot above that you might match getters and setters in
Resources
generated classes, to prevent this you can add a clause like&& !m.ParentType.IsUsing("System.Resources.ResourceManager")
:Of course, all this can be adapted to FxCop custom ruling system.
Disclamer: I work for NDepend