Solution
Since one attribute accepts a Type as a parameter (provided that it Type is derived from the expression typeof), you can use the "creativity".
So you need the attribute receive a string array as parameter but do not want to inform this array each time you decorate a member with this attribute, so that you want to get this array from a statement elsewhere, this statement you can change in the future or in one or another specific use of your attribute.
In order to have different array statements that will be passed as parameter to the attribute, you can declare an interface:
interface IAttributeArgument
{
string[] Argument { get; }
}
Declare one of the arrays that can be used as your parameter attribute declaring a class that implements this interface:
class AttributeArgument : IAttributeArgument
{
public string[] Argument { get { return new string[] { "a", "b", "c" }; } }
}
Now the array can be passed as a parameter to your attribute thus:
[CustomAttribute(typeof(AttributeArgument))]
public void Metodo() { }
In the implementation of its attribute, you can create an instance of Type passed by parameter and read the array like this:
class CustomAttribute : Attribute
{
public Type attributeArgument;
public CustomAttribute(Type attributeArgument)
{
this.attributeArgument = attributeArgument;
}
public string[] Argument
{
get
{
return ((IAttributeArgument)Activator.CreateInstance(attributeArgument)).Argument;
}
}
}
Tip: Attributes are metadata declarations
This solution, as well as any other you find for what you want to do, is a seasickness. See for example that the attribute would accept any Type but wishing to receive only one Type specific (in case, the interface), and this is bad code.
Has a reason to Attributes accept a limited range of types as a parameter, and the reason is that a attribute is a declaration of a metadata.
I repeat: statement. Decorate a limb with a attribute adds metadata to it that should be immediately understood by the programmer without having to resort to other points in the code.
That is, the ideal (expressive) way to pass parameters to a attribute is a literal value or the expression of a literal value, such as a constant or a Enum.
An example of what would be an expressive use of Attributes:
public class LinhaLidaDoArquivoTexto
{
[ColunaTipoData(ordem: 1, formatoData: "dd-MM-yyyy")]
public DateTime DataEnvio { get; set; }
[ColunaTipoDecimal(ordem: 2, formatoDecimal: "#0.00")]
public decimal ValorEnviado { get; set; }
...
}
The parameters passed to the attribute are not intended to be "variables". They are helping to declare, expressively, the class metadata.
You can’t use
[CustomAttribute({"a","b"})]
?– Jéf Bueno
Even for sure, but I’m in a great application and set all the values in the hand becomes unviable. I look for a way to encapsulate it
– anisanwesley
Because it needs to be a array? 'Cause it can’t be a string? You cannot change the way you use this attribute?
– Maniero
Because the values I need to pass on are more complex than that. The fact that it is an array is so you don’t have to pass dozens of strings in each attribute. Instead of passing
[CustomAttribute("a","b","c","d",..."outros 20 valores")]
I only inform the array. And if I need to change these items, I change only the array, and I don’t need to go out hunting code. As I said before: this is a great application, I can’t just put a string and leave it at that.– anisanwesley