hiddenUser
hiddenUser

Reputation: 692

Attribute with dynamic objects

I have the following attribute definition:

[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
class TestAttribute : Attribute
{
      public TestAttribute(List<string> values)
      {
      }
}

The following use of the attribute produces an error:

[Test(new List<string>() { "123", "456" }]
class A
{
}

The error is:

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

Any help please? I'm using Visual Studio 2012 .NET 4.5.

I don't want to use params string[] instead of List<string>.

Upvotes: 1

Views: 762

Answers (2)

poke
poke

Reputation: 388153

As the error message told you, you supply that as an argument to an attribute constructor. Generally anything you have to create with new is not valid as that is not constant but allocated at run time.

As the error message suggests, you could just use an array instead. In your case, it’s very simple to do with a params array:

public TestAttribute(params string[] values)
{ }

Then you can use it like this:

[Test("123", "456")]
class A
{ }

Note though, that you have defined TestAttribute to be only valid for methods, not for class declarations. So this will still fail.


I don't want to use params string[] instead of List<string>.

Well, you don’t have much of a choice, you could use a plain array, so you would have to write new string[] {"123", "456"} instead—that doesn’t give you any benefit though.

If you really want a list, although there really shouldn’t be a need for it, you can create it in the constructor:

public TestAttribute(params string[] values)
{
    List<string> valuesList = new List<string>(values);
}

I want to pass objects of specific types not something static.

You cannot ever pass anything dynamic to attributes. They are evaluated quite early when the declaration is processed, so at that time it’s unlikely that the rest of your code was executed.

Upvotes: 6

lightbricko
lightbricko

Reputation: 2709

Just like the message sais, it's simply not supported in c#. (The reason is that attributes are metadata and it should be possible to reflect/read metadata without executing code - such as initializing a list).

But you can use the params keyword:

[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
class TestAttribute : Attribute
{
    public TestAttribute(params string[] values)
    {
    }
}

[Test("123", "456")]
class A
{
}

Upvotes: 5

Related Questions