Принудительное использование настраиваемого атрибута
Сценарий:
У меня есть базовый класс "MyBase".
У меня есть пользовательский атрибут "MyAttrib"
С этим я делаю это:
[MyAttrib(1234)]
class MyClass : MyBase()
{
MyClass()
{
}
}
Вопрос:
Могу ли я каким-либо образом заставлять классы наследовать от MyBase иметь атрибут MyAttrib?
Ответы
Ответ 1
Нет, нет способа, чтобы компилятор требовал наличия атрибута в С#. У вас есть другие варианты, доступные вам. Вы можете написать unit test, который отражается на всех типах сборки и проверяет атрибут. Но, к сожалению, нет способа заставить компилятор использовать атрибут.
Ответ 2
Вы можете использовать PostSharp для этого.
Наследуйте свой класс атрибутов из класса OnMethodInvocationAspect (PostSharp) и переопределите метод CompileTimeValidate.
Немного похоже; хотя и наоборот (я только хотел, чтобы определенный атрибут мог применяться к классам, которые реализовали определенный интерфейс):
http://fgheysels.blogspot.com/2008/08/locking-system-with-aspect-oriented.html
Ответ 3
То, что я сделал, имело абстрактное свойство или метод в классе MyBase
, так что наследование классов вынуждено переопределять (и таким образом реализовать) это свойство/метод.
Не так чисто, как атрибут, но лучше, чем проверять во время выполнения, на мой взгляд.
Ответ 4
Если вы хотите, чтобы все классы базового типа или интерфейса имели атрибут, вы можете добавить простой unit test, который получает все производные классы и утверждает, что каждый из них имеет атрибут и добавляет результаты unit test в ваш дальнейший процесс сборки.
Ответ 5
Я больше не имею отношения к оригинальному постеру, я представляю, но здесь кое-что для тех, кому любопытно, как я, если это выполнимо.
Следующее работает, но, к сожалению, это не проверка во время компиляции, и поэтому я не могу честно рекомендовать его использовать. Вам лучше с интерфейсами, виртуалами и рефератами для большинства вещей.
Обязательный атрибут:
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
public class RequiredRandomThingAttribute : Attribute { /* ... */ }
Родительский класс, который требует его для производных классов:
public class ParentRequiringAttribute
{
public ParentRequiringAttribute()
{
if (this.GetType().GetCustomAttributes(typeof(RequiredRandomThingAttribute), false).Length == 0)
throw new NotImplementedException(this.GetType().ToString());
}
}
И чтобы подтвердить это все работает:
[RequiredRandomThing()]
public class CompleteSubclass : ParentRequiringAttribute { /* ... */ }
public class IncompleteSubclass : ParentRequiringAttribute { /* ... */ }
static public int Main(string[] args)
{
var test1 = new CompleteSubclass();
var test2 = new IncompleteSubclass(); // throws
}
Улучшить валидацию должно быть довольно легко, но мое собственное расследование на этом остановилось.