Is it possible to create an attribute that can be initialized with a variable number of arguments?
For example:
[MyCustomAttribute(new int[3,4,5])]
Yes, but you need to initialize the array that you are passing in. Here is an example from a row test in our unit tests that tests a variable number of command line options;
[Row( new[] { "-l", "/port:13102", "-lfsw" } )]
public void MyTest( string[] args ) { //... }
Try declaring the constructor like this:
public class MyCustomAttribute : Attribute
{
public MyCustomAttribute(params int[] t)
{
}
}
Then you can use it like:
[MyCustomAttribute(3, 4, 5)]
To piggy back on Marc Gravell's answer, yes you can define an attribute with array parameters but applying an attribute with an array parameter is not CLS-compliant. However just defining an attribute with an array property is perfectly CLS-compliant.
What made me realize this was that Json.NET, a CLS-compliant library, has an attribute class JsonPropertyAttribute with a property named ItemConverterParameters that's an array of objects.
Attributes will take an array. Though if you control the attribute, you can also use params
instead (which is nicer to consumers, IMO):
class MyCustomAttribute : Attribute {
public int[] Values { get; set; }
public MyCustomAttribute(params int[] values) {
this.Values = values;
}
}
[MyCustomAttribute(3, 4, 5)]
class MyClass { }
Your syntax for array creation just happens to be off:
class MyCustomAttribute : Attribute {
public int[] Values { get; set; }
public MyCustomAttribute(int[] values) {
this.Values = values;
}
}
[MyCustomAttribute(new int[] { 3, 4, 5 })]
class MyClass { }
That should be okay. From the spec, section 17.2:
An expression E is an attribute-argument-expression if all of the following statements are true:
Here's an example:
using System;
[AttributeUsage(AttributeTargets.All, AllowMultiple = false, Inherited = true)]
public class SampleAttribute : Attribute
{
public SampleAttribute(int[] foo)
{
}
}
[Sample(new int[]{1, 3, 5})]
class Test
{
}
You can do that. Another example could be:
class MyAttribute: Attribute
{
public MyAttribute(params object[] args)
{
}
}
[MyAttribute("hello", 2, 3.14f)]
class Program
{
static void Main(string[] args)
{
}
}