检查是否已使用具有相同值的属性

Check if Attribut with same value is already used

我正在写一种TLV de-/serialization class.

与 protobuf-net 一样,我有一个 classes 的合同属性和一个属性的成员属性。成员属性有一个标签号,就像在 protobuf 中一样。 现在我想检查标签号是否已被使用,最好的解决方案是是否存在某种编译器错误。如果这有帮助,我也有 postsharp。 class 结构如下所示:

[TlvContract]
public class Person{
    [TlvMember(1)]
    public String Name{get; set;}
    [TlvMember(2)]
    public Int32 ID{get; set;}
    // This should create a warning or compile error!!!!
    [TlvMember(1)]
    public String Town{get; set;}
}

除了 Roslyn 分析器之外,PostSharp 是一种可行的方法。

以下是此类检查和错误输出的基本实现:

[MulticastAttributeUsage(PersistMetaData = true)]
public class TlvContractAttribute : TypeLevelAspect
{
    public override void CompileTimeInitialize(Type target, AspectInfo aspectInfo)
    {
        Dictionary<int, PropertyInfo> indexes = new Dictionary<int, PropertyInfo>();

        foreach (PropertyInfo propertyInfo in target.GetProperties())
        {
            TlvMemberAttribute memberAttr =
                propertyInfo.GetCustomAttributes()
                    .Where(x => x is TlvMemberAttribute)
                    .Cast<TlvMemberAttribute>()
                    .SingleOrDefault();

            if (memberAttr == null)
            {
                Message.Write(MessageLocation.Of(propertyInfo), SeverityType.Error, "USR001",
                    "Property {0} should be marked by TlvMemberAttribute.", propertyInfo);

                continue;
            }

            if (indexes.ContainsKey(memberAttr.Index))
            {
                Message.Write(MessageLocation.Of(propertyInfo), SeverityType.Error, "USR002",
                    "Property {0} marked by TlvMemberAttribute uses Index {1}, which is already used by property {2}.",
                    propertyInfo, memberAttr.Index, indexes[memberAttr.Index]);

                continue;
            }

            indexes[memberAttr.Index] = propertyInfo;
        }
    }
}

它在您定义它的程序集中工作。您只需要确保 PostSharp 实际上在您希望检查工作的所有程序集上运行。

如果您的属性需要不同的基础 class,您还可以实现 ITypeLevelAspectITypeLevelAspectBuildSemantics 接口。