Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing static array in attribute

Is it possible to circumvent the following restriction:

Create a static readonly array in a class:

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

Then pass it as a parameter to an attribute:

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

    FooAttribute()
    {
    }
}

--- Let's say Box is a property of class A ---

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

I know this won't compile and will result in this error:

"An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type".

Is it possible to go around this somehow to be able to use the static array ? I'm asking since this will be much more convenient maintenance-wise, since I have a lot of properties.

Thanks in advance.

like image 704
Omri Aharon Avatar asked May 23 '13 09:05

Omri Aharon


2 Answers

No, basically.

You could, however, subclass the attribute and use that, i.e.

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

or:

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

and decorate with [AwesomeFoo] instead. If you use reflection to look for FooAttribute, it will work as expected:

[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
        }
    }
}

You could perhaps nest this inside A, so you are decorating with:

[A.FooMonths]

or similar

like image 175
Marc Gravell Avatar answered Sep 24 '22 02:09

Marc Gravell


Unfortunately this is not possible. The attributes (including the values of their arguments) are placed into the assembly metadata by the compiler so it has to be able to evaluate them at compile time (hence the restriction to constant expressions; the exception for array creation expressions was obviously made because otherwise you could not have array arguments at all).

In contrast, the code that actually initializes A.Months is only executed at runtime.

like image 23
Jon Avatar answered Sep 25 '22 02:09

Jon