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

Намерение:

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

Реализация:

[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.

    }
}

Затем целевое перечисление помечается следующим образом

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

Проблема:

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

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


person Sisyphus    schedule 31.08.2014    source источник
comment
возможный дубликат класса атрибута, не вызывающего конструктор   -  person Patrick Hofman    schedule 31.08.2014
comment
Я зашел в эту тему до того, как написал свой пост, но, к сожалению, он не смог решить мою проблему.   -  person Sisyphus    schedule 31.08.2014
comment
Что не работает, если следовать другому ответу?   -  person Patrick Hofman    schedule 31.08.2014
comment
Извините, я не понимаю, что именно вы имеете в виду.   -  person Sisyphus    schedule 31.08.2014
comment
Почему этот пост не решил вашу проблему?   -  person Patrick Hofman    schedule 31.08.2014


Ответы (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.
    }
}
person Lucas Trzesniewski    schedule 31.08.2014
comment
Это единственный способ, который вызывает срабатывание конструктора атрибутов? почему атрибуты класса автоматически срабатывают при создании экземпляра класса? - person Sisyphus; 31.08.2014
comment
Да, это единственный способ. И нет, они тоже не стреляют. - person Patrick Hofman; 31.08.2014
comment
Потому что это атрибуты. Это просто данные, если кто-то не решит их активировать. - person david.pfx; 31.08.2014
comment
@user2080257 user2080257 Просто добавлю к этому: я бы предпочел переместить ваш проверочный код из конструктора атрибутов в код запуска. Таким образом, проверка не будет запускаться случайно несколько раз, если какой-то другой код имеет дело с отражением. Атрибуты должны ограничиваться хранением данных. - person Lucas Trzesniewski; 31.08.2014
comment
@user2080257 user2080257 Код, который я разместил в ответе, я думаю, вы хотите запускать его при запуске - person Lucas Trzesniewski; 01.09.2014
comment
Пожалуйста, объясните подробнее, что вы подразумеваете под запуском, например, как в событии Application_Start в приложениях ASP.net? - person Sisyphus; 01.09.2014
comment
@user2080257 user2080257 Да, это хорошая отправная точка в ASP.NET. Но я имею в виду, куда бы вы ни поместили код моего ответа, на самом деле. - person Lucas Trzesniewski; 01.09.2014