Создание пользовательского CodeAccessSecurityAttribute приводит к исключению при компиляции

Я создаю собственный CodeAccessSecurityAttribute для обработки авторизации для моих служб WCF. Я построил класс А как таковой:

public class A : CodeAccessSecurityAttribute
{
    public A() : base(SecurityAction.Demand)
    {
        // Constructor Code
    }

    public override IPermission CreatePermission()
    {
        // Permission Creation Code
    }

}

И при компиляции выдает эту ошибку.

Error emitting 'A' attribute -- 'Serialized security custom attribute is 
truncated or incorrectly formed.'

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

public class B : CodeAccessSecurityAttribute
{
    public B(SecurityAction Action) : base(Action)
    {
        // Constructor Code
    }

    public override IPermission CreatePermission()
    {
        // Permission Creation Code
    }

}

Я знаю, это потому, что перечисление SecurityAction не имеет прямой ссылки на открытую часть класса A, но я не могу понять, как сделать это так, чтобы я мог сделать это методом класса A вместо класса B.

2 ответа

Решение

Я не знаю точную причину требования, но документация MSDN на CodeAccessSecurityAttribute ясно заявляет

Примечания для наследников

Все атрибуты разрешений, полученные из этого класса, должны иметь только один конструктор, который принимает SecurityAction в качестве единственного параметра.

Изменено: причина этого требования заключается в том, что CodeAccessSecurityAttribute с низкоуровневой точки зрения сильно отличается от других пользовательских атрибутов. Как правило, пользовательские атрибуты хранятся в скомпилированных метаданных в CustomAttribute Таблица. Но атрибуты безопасности, вытекающие из SecurityAttribute, хранятся отдельно в DeclSecurity Таблица. И эта таблица не содержит общих данных, таких как таблица CustomAttribute, эта таблица содержит значение Action, имя типа атрибута, плюс набор свойств (именованных аргументов), как в случае с пользовательским атрибутом. Таким образом, компилятору необходимо преобразовать общий синтаксис настраиваемых атрибутов в запись в этой таблице метаданных, поэтому он должен следовать фиксированной форме, указанной выше. (См. Также это сообщение в блоге или Раздел II, раздел 22.11 DeclSecurity: 0x0E стандарта Common Language Infrastructure (CLI).)

Если вы предоставляете конструктору значение по умолчанию, вам не нужно указывать его в атрибуте.

public class B : CodeAccessSecurityAttribute 
{ 
    public B(SecurityAction Action = SecurityAction.Demand) : base(Action) 
    { 
        // Constructor Code 
    } 

    public override IPermission CreatePermission() 
    { 
        // Permission Creation Code 
    } 
} 
Другие вопросы по тегам