我正在编写自定义安全属性并得到奇怪的编译器行为...当我在同一文件中使用该属性时,默认参数值工作正常:
using System.Security.Permissions;
[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) { }
}
但是当我将上面的代码分成两个文件时 - 文件1:
using System.Security.Permissions;
[System.Serializable]
sealed class FooAttribute : CodeAccessSecurityAttribute {
public FooAttribute(SecurityAction action = SecurityAction.Demand) : base(action) { }
public override System.Security.IPermission CreatePermission() { return null; }
}
文件2:
[Foo] class Program {
static void Main(string[] args) { }
}
我遇到编译错误:
错误: 'FooAttribute' 不包含构造函数 取0个参数
这只发生在CodeAccessSecurityAttribute
个继承者身上,看起来很奇怪......
答案 0 :(得分:13)
所以我没有确切的答案,但我尽可能地调查它。我想我理解为什么当你继承CodeAccessSecurityAttribute
而不是SecurityAttribute.
时会发生这种情况如果你看一下从Foo
继承时应用CodeAccessSecurityAttribute
属性时生成的IL它看起来像这样:
.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。
如果我们将Foo声明更改为如下,则更多地查看IL
[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类之后才会看到可选参数。然后,它必须在构建过程中以某种方式使用该元数据,这是您看到失败的地方。对于任何更多细节,我们必须希望有人知道编译器,即Eric可以对它有所了解。我会在connect.microsoft.com上提交它作为建议的评论之一,因为它似乎是由于遍历订单而导致的错误。