C# 允许派生类的多个属性

标签 c# attributes

考虑下面的代码片段:

[AttributeUsage(AttributeTargets.Class, AllowMultiple =true)]
public class FooAttribute : Attribute {
    public string Bar { get; set; } 
}

[Foo(Bar = "A")]
public class A{}

[Foo(Bar = "B")]
public class B : A{}

[Foo(Bar = "C")]
public class C : B{}

如果我尝试获取 C 类的 FooAttribute

var attrList = typeof(C).GetCustomAttributes(typeof(FooAttribute), true) as FooAttribute[];

我将获得所有 3 个属性。顺序是C, B, A。所以这是我的问题:

  • 此顺序是否是一种有保证的行为,这意味着派生类的属性总是出现在比其基类更小的索引处?
  • 是否可以知道属性附加到哪个特定类型?

最佳答案

通常无法保证顺序,编译器会根据平台、文化和编译器版本产生不同的结果。但是,在这种特定情况中,可以保证顺序正确(至少部分正确)。异常(exception)是当您在同一继承级别分配多个属性时:

[AttributeUsage(AttributeTargets.Class, AllowMultiple =true)]
public class FooAttribute : Attribute {
    public string Bar { get; set; } 
}

[Foo(Bar = "A")]
public class A{}

[Foo(Bar = "B"), Foo(Bar = "C")]
public class B : A{}

A 的顺序始终相同(最后),但 B 和 C 可以不同:C-B-A 或 B-C-A。在以下示例中,根本无法保证顺序:

[Foo(Bar = "A"), Foo(Bar = "B"), Foo(Bar = "C")]
public class A{}

但是如果您将一个属性分配给每个继承级别,顺序将保持不变。这是由于 .NET (Framework) 中的实现,因为它遍历每个基本类型以收集所有属性(如果您 Type.GetCustomAttributes(Type, inherit: true))。这个可以看这段代码(System.Private.CoreLib, System.Reflection):

private static Attribute[] InternalGetCustomAttributes(EventInfo element, Type type, bool inherit)
{
    [...]

    // walk up the hierarchy chain
    Attribute[] attributes = (Attribute[])element.GetCustomAttributes(type, inherit);
    if (inherit)
    {
        // create the hashtable that keeps track of inherited types
        Dictionary<Type, AttributeUsageAttribute> types = new Dictionary<Type, AttributeUsageAttribute>(11);
        // create an array list to collect all the requested attibutes
        List<Attribute> attributeList = new List<Attribute>();
        CopyToArrayList(attributeList, attributes, types);

        EventInfo? baseEvent = GetParentDefinition(element);
        while (baseEvent != null)
        {
            attributes = GetCustomAttributes(baseEvent, type, false);
            AddAttributesToList(attributeList, attributes, types);
            baseEvent = GetParentDefinition(baseEvent);
        }
        Attribute[] array = CreateAttributeArrayHelper(type, attributeList.Count);
        attributeList.CopyTo(array, 0);
        return array;
    }
    else
        return attributes;
}

请注意,这适用于 events,但对于 MemberInfo(Type)也是如此。

关于C# 允许派生类的多个属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68372586/

相关文章:

c# - 如何在 C# 中取消扁平化的 json

c# - 当另一个控件与它重叠时隐藏控件

c# - WinForm DataBinding 业务对象 C# .NET 中的隐藏属性

ruby-on-rails - attr_accessor 和类实例调试

python - Python方法调用问题

c# - 有没有办法检查结果集中的一行或多行总和是否为特定值?

c# - 将 Lync 2010 与外部程序集成

c# - 关于 C# 中的简单继承

python - Odoo - 添加自定义字段属性?

javascript - 使用 JavaScript 获取输入字段的 Id