Подтвердить что ты не робот

Принудительное использование настраиваемого атрибута

Сценарий: У меня есть базовый класс "MyBase". У меня есть пользовательский атрибут "MyAttrib"

С этим я делаю это:

[MyAttrib(1234)]
class MyClass : MyBase()
{
 MyClass()
 {
 }
}

Вопрос: Могу ли я каким-либо образом заставлять классы наследовать от MyBase иметь атрибут MyAttrib?

4b9b3361

Ответ 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
}

Улучшить валидацию должно быть довольно легко, но мое собственное расследование на этом остановилось.