简体   繁体   English

如何在自定义FxCop规则中检测自动实现的属性?

[英]How to detect an auto-implemented property in a custom FxCop rule?

I'm trying to write a rule for DTOs, that only allows auto-implemented properties. 我正在尝试为DTO编写一个规则,它只允许自动实现的属性。 How do you detect that a property is auto-implemented using the FxCop API? 如何使用FxCop API检测到属性是自动实现的?

Actually there is a difference between auto-properties and properties implemented by user in the IL compiled code. 实际上,用户在IL编译代码中实现的自动属性和属性之间存在差异。 Auto-properties setters and getters are tagged with System.Runtime.CompilerServices.CompilerGeneratedAttribute . 自动属性设置器和getter使用System.Runtime.CompilerServices.CompilerGeneratedAttribute标记。

自动属性编译IL代码

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: 因此,使用NDepend工具, 您可以通过C#LINQ查询编写自定义代码查询和自定义代码规则 ,匹配自动属性getter和setter只需编写LINQ查询:

from m in Application.Methods
where (m.IsPropertyGetter|| m.IsPropertySetter)
    && m.IsGeneratedByCompiler
select m

NDepend自动属性代码查询匹配

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") : 请注意,在上面的屏幕截图中,您可能会在Resources生成的类中匹配getter和setter,为了防止这种情况,您可以添加像&& !m.ParentType.IsUsing("System.Resources.ResourceManager")这样的子句:

NDepend自动属性代码查询匹配,无需资源匹配

Of course, all this can be adapted to FxCop custom ruling system. 当然,所有这些都可以适应FxCop定制裁决系统。

Disclamer: I work for NDepend 免责声明:我为NDepend工作

Thank you @Patrick from NDepend team. 谢谢NDepend团队的@Patrick。 Here's the code for the resulting FxCop rule. 这是生成的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)));
            }
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM