3

I have custom attribute that takes array of objects. I am trying to pass an array of objects to it, but receive compiler error:

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

Here is the code:

[AttributeUsage(AttributeTargets.Class)]
public class MyAttribute : Attribute
{
    public MyAttribute(Person[] people)
    {
         People = people;
    }

    public Person[] People{get; private set;}
}

public class Person
{
    public string Name{get;set;}
    public string LastName{get;set;}
}

I saw some articles online, but haven't seen any closer to mine. Am I doing something wrong or it is bug? If it is not bug can someone explain why I can't pass array of Person? I tried array of string and it works fine.

Victor
  • 3,669
  • 3
  • 37
  • 42
Dilshod
  • 3,189
  • 3
  • 36
  • 67

2 Answers2

5

It's because an array of string is a compile-time constant whereas an array of Person is not. This isn't a bug, it's a limitation. The best way around it, that I've found, is by using reflection to set the attributes properties on creation of the object - but it's not pretty.

Mike Perrenoud
  • 66,820
  • 29
  • 157
  • 232
  • Thanks for the explaining. Do you know why it is limited? What is wrong passing array of objects? – Dilshod Sep 09 '13 at 20:07
  • 2
    @Dilshod, attributes are applied to the `Type`, not the object. This means that there's no real way for the CLR to apply them to individual objects. – Mike Perrenoud Sep 09 '13 at 20:08
  • @Dilshod, in your case the best approach would be to pass an array of strings to the attribute and then load those `Person` objects at run-time. – Mike Perrenoud Sep 09 '13 at 20:09
  • @Dilshod, here is some more [reading by Eric Lippert](http://stackoverflow.com/questions/16876208/if-attributes-are-only-constructed-when-they-are-reflected-into-why-are-attribu). – Mike Perrenoud Sep 09 '13 at 20:11
  • in my real app I have two parameters, one is array of strings and second parameter is array of MyClass. I need to pass List>. I could pass array of strings, but is it efficient way of doing this? – Dilshod Sep 09 '13 at 20:12
  • @Dilshod, you can probably pass that key value pair (though I don't **know** that it will compile). If you can pass the KVP then do so, it's a more accurate representation of the data model. – Mike Perrenoud Sep 09 '13 at 20:13
  • List> didn't work too. not sure which way will be very efficient. – Dilshod Sep 09 '13 at 20:21
  • @Dilshod you'll probably need to stick with string arrays then and just use indexes to initialize what you need. – Mike Perrenoud Sep 09 '13 at 20:22
  • 1
    Yes, it looks like there is no more options. Thanks for the help! – Dilshod Sep 09 '13 at 20:23
1

I think the error quoted comes when you try to apply your attribute to some code element. As in:

[My(new[] { new Person(), })]

You cannot use an array like that. While the expression in () is an array creation expression, it is not an array creation expression of an attribute parameter type since, by definition, the class Person is not an attribute parameter type.

Jeppe Stig Nielsen
  • 60,409
  • 11
  • 110
  • 181