10

是否可以绕过以下限制:

在类中创建一个静态只读数组:

public class A
{
    public static readonly int[] Months = new int[] { 1, 2, 3};
}

然后将其作为参数传递给属性:

public class FooAttribute : Attribute
{
    public int[] Nums { get; set; }

    FooAttribute()
    {
    }
}

--- 假设 Box 是 A 类的属性 ---

[Foo(Nums = A.Months)]
public string Box { get; set; }

我知道这不会编译并会导致此错误:

“属性参数必须是属性参数类型的常量表达式、typeof 表达式或数组创建表达式”。

是否有可能以某种方式解决这个问题以便能够使用静态数组?我在问,因为这在维护方面会更方便,因为我有很多属性。

提前致谢。

4

3 回答 3

12

不,基本上。

但是,您可以将属性子类化并使用它,即

class AwesomeFooAttribute : FooAttribute {
    public AwesomeFooAttribute() : FooAttribute(A.Months) {}
}

或者:

class AwesomeFooAttribute : FooAttribute {
    public AwesomeFooAttribute() {
        Nums = A.Months;
    }
}

并用[AwesomeFoo]代替装饰。如果您使用反射来查找FooAttribute,它将按预期工作:

[AwesomeFoo]
static class Program
{
    static void Main()
    {
        var foo = (FooAttribute)Attribute.GetCustomAttribute(
            typeof(Program), typeof(FooAttribute));
        if (foo != null)
        {
            int[] nums = foo.Nums; // 1,2,3
        }
    }
}

你也许可以把它嵌套在里面A,所以你正在装饰:

[A.FooMonths]

或类似的

于 2013-05-23T09:48:33.440 回答
11

不幸的是,这是不可能的。属性(包括它们的参数的值)由编译器放入程序集元数据中,因此它必须能够在编译时评估它们(因此限制了常量表达式;数组创建表达式的例外显然是因为否则你根本不能有数组参数)。

相反,实际初始化的代码A.Months只在运行时执行。

于 2013-05-23T09:47:22.450 回答
5

简短的回答:没有。

但是你可以按键引用 int 数组:

public class A
{
    public static readonly Dictionary<int, int[]> NumsArrays 
              = new[]{{1, new[]{1,1,1}}, {2, new[]{2,2,2}}, {3, new[]{3,3,3}}};
    public const int Num1 = 1;
    public const int Num2 = 2;
    public const int Num3 = 3;
}

public class FooAttribute : Attribute
{
    public int NumsId { get; set; }

    FooAttribute()
    {
    }
}

[Foo(NumsID = A.Num3)]
public string Box { get; set; }

//Evaluation:
int id = (FooAttribute) Attribute.GetCustomAttribute(type, typeof (FooAttribute));
int[] result = A.NumsArrays[id];//result is {3,3,3}
于 2013-05-23T09:49:16.800 回答