Так что у меня нет точного ответа, но я взял его так далеко, как только мог, изучив его. Я думаю, я понимаю, почему это происходит, когда вы наследуете от CodeAccessSecurityAttribute
, а не SecurityAttribute.
Если вы посмотрите на IL, сгенерированный при применении атрибута Foo
, когда он наследуется от CodeAccessSecurityAttribute
, это выглядит так:
.permissionset demand = {class 'ConsoleApplication1.FooAttribute, ConsoleApplication1, Version=1.0.0.0, Culture=neutral' = {}}
Когда Foo
наследует от SecurityAttribute, это выглядит так:
.custom instance void ConsoleApplication1.FooAttribute::.ctor(valuetype [mscorlib]System.Security.Permissions.SecurityAction) = ( 01 00 02 00 00 00 00 00 )
Очевидно, что CodeAccessSecurityAttribute радикально изменяет IL, сгенерированный путем применения атрибута.
Если посмотреть на IL, мы изменим объявление Foo следующим образом
[Foo(SecurityAction.Demand)]
Мы получаем следующий IL:
.permissionset demand = {class 'ConsoleApplication1.FooAttribute, ConsoleApplication1, Version=1.0.0.0, Culture=neutral' = {}}
То же самое, что было, когда мы не указали необязательный параметр. Кроме того, мы можем вызвать ошибку, не просто разделив атрибут и класс Program
на отдельные файлы, мы можем вызвать ее, переставив файлы в классе следующим образом:
[Foo]
class Program
{
static void Main(string[] args) {}
}
[System.Serializable]
sealed class FooAttribute : CodeAccessSecurityAttribute
{
public FooAttribute(SecurityAction action = SecurityAction.Demand) : base(action) { }
public override System.Security.IPermission CreatePermission() { return null; }
}
Еще интереснее, если мы сделаем следующее с классами Other
и Other2
, выдадим ошибку, а Program
- нет. Только классы, которые предшествуют Foo
в файле, будут иметь ошибку
[Foo]
class Other
{
}
[Foo]
class Other2
{
}
[System.Serializable]
sealed class FooAttribute : CodeAccessSecurityAttribute
{
public FooAttribute(SecurityAction action = SecurityAction.Demand) : base(action) { }
public override System.Security.IPermission CreatePermission() { return null; } }
[Foo]
class Program
{
static void Main(string[] args) {}
}
Что это говорит мне о том, что где-то есть проблема в процессе сборки. Я недостаточно знаю, как работает Code Access Security, чтобы понять, в чем именно заключается проблема. Должна быть часть процесса, который просматривает CodeAccessSecurityAttributes и что-то делает с попыткой применить SecurityAction к коду. Я предполагаю, что это создает какие-то метаданные для сборки. Он должен делать это каким-то упорядоченным образом, чтобы не видеть необязательный параметр до тех пор, пока он не пройдет класс Program. Затем он должен каким-то образом использовать эти метаданные в процессе сборки, и именно здесь вы видите сбой. Для более подробной информации мы будем надеяться, что кто-то, кто знает компилятор, то есть Эрик, может пролить свет на это. Я бы отправил его на connect.microsoft.com в качестве одного из предложенных комментариев, так как кажется, что это ошибка, вызванная порядком прохождения.