Создание пользовательского 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
}
}