Intrepid
Intrepid

Reputation: 2831

Struct parameters in attributes

I have got the following sample code:

public struct TestData
{
    public readonly string Element;
    public readonly bool MandatoryInd;

    public TestData( string element, bool mandatoryInd )
    {
        Element = element;
        MandatoryInd = mandatoryInd;
    }
}

[AttributeUsage( AttributeTargets.Class, AllowMultiple = false )]
public class Test : Attribute
{
    public TestData[] Values { get; set; }

    public Test( params TestData[] values )
    {
        this.Values = values;
    }
}

What I want to do is something like this:

[Test( "3477", true, "3286", true, "3286", false )]
public class TestClass
{

}

Basically, I'd like a pair of parameters (string, bool) to be captured in the TestData() struct, but I am not sure if it's possible to do this. I have tried the following, but I get a compile error "An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type".

[Test( new TestData("3477", true), new TestData("3286", true), new TestData("3286", false) )]
public class TestClass
{

}

If this isn't possible then I will have to consider using multiple attributes, which I am doing successfully at the moment but I want a cleaner and more terser method.

Upvotes: 4

Views: 4401

Answers (2)

Marc Gravell
Marc Gravell

Reputation: 1064014

Indeed, that isn't possible. Either use a string and parse it; or use multiple attribute declarations, i.e.

[Test]
[TestData("3477", true)]
[TestData("3286", true)]
[TestData("3286", false)]
public class TestClass {...}

Upvotes: 1

Selman Genç
Selman Genç

Reputation: 101711

This is possible if you change the signature of your constructor and use a linq trick:

public Test(params object[] values)
{
     this.Values = values
            .Select((x, idx) => new {x, idx})
            .GroupBy(g => g.idx/2)
            .Select(g => new TestData(g.First().x.ToString(), (bool) g.Last().x))
            .ToArray();

}

But indeed it is not type-safe.

Note: You may want to use Batch method from MoreLINQ then your code will look better.

Upvotes: 2

Related Questions