Ответ 1
Итак, у меня нет точного ответа, но я взял его, насколько мог, заглядывая в него. Я думаю, что я понимаю, почему это происходит, когда вы наследуете от 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 к коду. Я предполагаю, что он создает какие-то метаданные для сборки. Он должен делать это каким-то упорядоченным способом, чтобы не видеть необязательный параметр, пока он уже не прошел класс программы. Затем он должен использовать эти метаданные каким-то образом во время процесса сборки, и именно там вы видите сбой. Для более подробной информации нам нужно надеяться, что кто-то знает компилятор, т.е. Эрик может пролить свет на него. Я бы отправил его на connect.microsoft.com в качестве одного из комментариев, предложенных, поскольку кажется, что ошибка, вызванная перемещением вещей, проходит.