覆盖派生类上的自定义属性

本文关键字:自定义属性 派生 覆盖 | 更新日期: 2023-09-27 18:35:29

我们有一个自定义属性

[AttributeUsage(AttributeTargets.All, AllowMultiple = true)]
public class CustomDesignerAttribute: Attribute

然后我们有一个用此属性装饰的基类

[CustomDesigner(someKey, someValue)]
public class BaseClass

然后我们有一个从这个派生的类,用相同的属性装饰(具有相同的键,不同的值)

[CustomDesigner(someKey, someOtherValue)]
public class ChildClass : BaseClass

ChildClass 是否有可能不创建属性的副本,而是覆盖现有键的值(覆盖整个父属性)?如果不是,如果 ChildClass 没有定义自己的默认值,那么从 BaseClass 获取默认值的最佳模式是什么?

覆盖派生类上的自定义属性

不,无法覆盖现有属性。

属性是附加到对象(程序集、类、方法、变量等)的元数据,因此它们始终保持此连接

如果要在基类中给出默认的"行为"并在某些派生类中覆盖它,则必须检查GetCustomAttributes()返回的所有属性,以便仅使用派生最多的属性(列表中的第一个)。

使用 [AttributeUsage(Inherited=false)] 来防止派生类继承该属性。

我认为可以

通过以下方式:

1. 使用类型描述符

在您的CustomDesignerAttribute覆盖TypeId

public override object TypeId
{
     get
     {
         return Key.GetHashCode();
      }
 }

TypeId的基本实现仅使用属性类型,因此不涉及任何参数。

然后你可以使用 TypeDescriptor.GetAttributes(typeof(ChildClass)).OfType<CustomDesignerAttribute>()

TypeDescriptor(与GetType().GetCustomAttributes相反)仅返回一个基于相同TypeId的属性。我测试了它,它是与返回的TypeId匹配的最派生属性。

因此,如果您的TypeId表示属性的键,那么您可以在派生类上覆盖它 - 当使用 TypeDescriptor 获取属性时!请注意,只要它们的键不同,仍然可以使用多个属性。

注意:类型描述符还查找动态添加的属性(在运行时添加)

2. 使用删除属性

您可以向CustomDesignerAttribute添加公共bool Remove { get; set; }。可以将其设置为在派生类中true,同时设置与要删除的基类属性相同的其他参数。然后将另一个具有相同键但所需值的属性添加到派生类中。获取属性时,必须以智能方式评估 Remove 属性。要么使用 TypeDescriptor(如 1) 和 TypeId例如返回 Key.HashCode() + Value.GetHashCode() 或使用 GetType().GetCustomAttributes ,在这两种方式中,您都必须遍历属性列表和过滤器。您必须知道这些列表的顺序,如果大多数派生类型是第一个还是相反。