Consider the following attribute.
internal class NiceAttribute : Attribute
{
private string _stuff;
public string Stuff
{
set { _stuff = value; }
}
}
When I try to use the attribute [Nice(Stuff = "test")]
the compiler gives the following error.
'Stuff' is not a valid named attribute argument. Named attribute arguments must be fields which are not readonly, static, or const, or read-write properties which are public and not static.
What is the rational behind the requirement for the property to be readable?
Update
I will try to sketch my use case for having write-only properties on attributes.
interface ISettingsBuilder
{
Settings GetSettings();
}
class SettingsAttribute : Attribute, ISettingsBuilder
{
private readonly IDictionary<string, object> _settings =
new Dictionary<string, object>();
public Settings GetSettings()
{
// Use _settings to create an immutable instance of Settings
}
public string Stuff
{
set { _settings["Stuff"] = value; }
}
// More properties ...
}
There may be other implementations of ISettingsBuilder
. For example one that offers a nice API to build settings through code.
I ended up with implementing my getters by throwing a NotImplementedException
.
public string Stuff
{
get { throw new NotImplementedException(); }
set { _settings["Stuff"] = value; }
}
Can you think of a nicer way to do something like this?
I suspect the compiler is using a slightly misguided check to see whether you are accessing a private property here
Edit "we" have now located the actual source. For informational purposes, here is the full breakdown, but feel free to skip to the bottom.
(note how bug should be filed against the Mono compiler. I'll think that one over for a while)
'reference' is not a valid named attribute argument. Named attribute arguments must be fields which are not readonly, static or const, or read-write properties which are not static.
An attempt was made to access a private member of an attribute class.
It could seem that it is using some kind of lookup (akin to reflection) to make sure that the getter is accessible and if it isn't, concludes that it must be private.
Which, of course, it doesn't need to be :)
For fun, observe that the mono compiler has no problem whatsoever accepting this attribute: https://ideone.com/45fCX
Of course it could be that the compiler requires attribute parameters to have reflectable values. If the property wasn't publicly readable, you could only use reflection to 'observe' that the attribute is present, not with what parameter it was initialized.
I don't know exactly, why such a design choicde would have been made, but it does make sense if you factor in reflection usage.
Update @Arun posted the relevant quote that confirms this conjecture (thanks!):
Accessing Attributes Through Reflection Once attributes have been associated with program elements, reflection can be used to query their existence and values. The main reflection methods to query attributes are contained in the System.Reflection.MemberInfo class (GetCustomAttributes family of methods).
So the reason must be: Attribute parameters must have reflectible values
Prize question: How does that work with positional parameters? How would one reflect those?
This link is a reference from Visual Studio 2003, but I guess it hardly changed.
Relevant portion from that link:
Accessing Attributes Through Reflection Once attributes have been associated with program elements, reflection can be used to query their existence and values. The main reflection methods to query attributes are contained in the System.Reflection.MemberInfo class (GetCustomAttributes family of methods).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With