Когда выполняется конструктор пользовательских атрибутов?

Намерение:

Я пишу бизнес-приложение, которое использует несколько перечислений, где большинство этих перечислений также существует в таблицах базы данных. Проблема заключается в обслуживании, когда один из членов команды или поздний разработчик изменяет значение члена перечисления в одном из двух мест, оставляя перечисление несинхронизированным. Чтобы решить эту проблему, я пытаюсь создать пользовательский атрибут enum, который выдает какое-то исключение, когда обнаруживает, что значения enum не синхронизированы.

Реализация:

[AttributeUsage(AttributeTargets.Enum)]
public class EnumSyncAtrribute : Attribute
{

    public EnumSyncAtrribute(Type databaseAccessType, Type enumType))
    {

        // Code that uses that databaseAccessType to access the database to get
        // enum values then compare it to values of enumType , goes here.

    }
}

Тогда целевой enum помечается следующим образом

[EnumSyncAtrribute(typeof(MyDataBaseAccess), typeof(MyEnum))]
public enum MyEnum
{
    value1 = 0,
    value2 = 1,
    value3 = 2
}

Проблема:

Проблема в том, что этот конструктор атрибута никогда не выполняется! Я попытался заменить Enums классами и обнаружил, что он работает нормально, а с Enums - нет!

Вопрос в том, когда пользовательские атрибуты используются для перечислений, когда выполняются их конструкторы?

1 ответ

Решение

Атрибут создается только при извлечении его (используя GetCustomAttribute функция). В противном случае его рецепт построения (перегрузка конструктора + позиционные параметры + значения свойств) сохраняется только в метаданных сборки.

В вашем случае я бы забрал все типы перечислений из сборки и проверил, имеют ли они атрибут. Нечто подобное при запуске вашего приложения:

var allEnumTypes = Assembly.GetExecutingAssembly()
                           .GetTypes()
                           .Where(t => t.IsEnum);

foreach(var enumType in allEnumTypes)
{
    var syncAttr = Attribute.GetCustomAttribute(enumType, typeof(EnumSyncAtrribute)) as EnumSyncAtrribute;
    if (syncAttr != null)
    {
        // Possibly do something here, but the constructor was already executed at this point.
    }
}
Другие вопросы по тегам