Перезаписать customattribute на производном классе

У нас есть настраиваемый атрибут

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

то у нас есть базовый класс, украшенный этим атрибутом

[CustomDesigner(someKey, someValue)]
public class BaseClass

то у нас есть класс, полученный из этого, украшенный тем же атрибутом (с тем же ключом, другим значением)

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

Возможно ли, что ChildClass не создаст дубликат атрибута, но вместо этого заменит значение существующего ключа (перезаписывает весь родительский атрибут)? Если нет, то какой лучший шаблон для получения значения по умолчанию из BaseClass, если ChildClass не определил его?

Ответ 1

Нет, невозможно переопределить существующий атрибут.

Атрибуты - это метаданные, привязанные к объекту (сборка, класс, метод, переменная и т.д.), поэтому они всегда поддерживают это соединение.

Если вы хотите дать по умолчанию "поведение" в базовом классе и переопределить его в некоторых производных классах, вы должны проверить все атрибуты, возвращаемые GetCustomAttributes(), чтобы использовать только самый производный (первый в списке).

Ответ 2

Я думаю, что это возможно следующим образом:

1. Использование TypeDescriptor

В CustomDesignerAttribute переписать TypeId:

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

Базовая реализация TypeId просто использует тип атрибута, поэтому никакие параметры не будут задействованы.

Тогда u может использовать TypeDescriptor.GetAttributes(typeof(ChildClass)).OfType<CustomDesignerAttribute>()

TypeDescriptor (в отличие от GetType().GetCustomAttributes) возвращает только один атрибут, основанный на том же TypeId. Я тестировал его, и это самый производный атрибут, соответствующий возвращаемому TypeId.

Итак, если ваш TypeId представляет ключ вашего атрибута, вы можете перезаписать его на производных классах - при использовании TypeDescriptor для получения атрибута! Обратите внимание, что все еще возможны несколько атрибутов, если они различаются по своему ключу.

Примечание. TypeDescriptor также находит динамически добавленные атрибуты (добавленные во время выполнения)

2. Использование Remove Property

Вы можете добавить общедоступный bool Remove { get; set; } к вашему CustomDesignerAttribute. Вы можете установить его в true в производном классе, установив другие параметры, идентичные атрибуту базового класса, который вы хотите удалить. Затем добавьте еще один атрибут с тем же ключом, но вы хотите получить свой производный класс. При получении атрибутов вы должны оценивать свойство "Удалить" интеллектуальным образом. Либо используя TypeDescriptor, как в 1) с помощью TypeId, например. возвращая Key.HashCode() + Value.GetHashCode() или используя GetType().GetCustomAttributes, в обоих направлениях вам нужно пройти через список атрибутов и фильтр. Вы должны знать, в каком порядке эти списки, если большинство производных типов сначала или наоборот.

Ответ 3

используйте [AttributeUsage(Inherited=false)], чтобы предотвратить наследование унаследованного класса производным классом.