考虑以下属性。
internal class NiceAttribute : Attribute
{
private string _stuff;
public string Stuff
{
set { _stuff = value; }
}
}
当我尝试使用属性[Nice(Stuff = "test")]
时,编译器会出现以下错误。
'Stuff'不是有效的命名属性参数。命名属性 参数必须是非readonly,static或const的字段,或者 读写属性,这些属性是公开的而非静态的。
要求该属性可读的理由是什么?
更新
我将尝试绘制我的用例,以便在属性上具有只写属性。
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 ...
}
ISettingsBuilder
可能还有其他实现。例如,提供一个很好的API来通过代码构建设置。
我最终通过抛出NotImplementedException
来实现我的吸气剂。
public string Stuff
{
get { throw new NotImplementedException(); }
set { _settings["Stuff"] = value; }
}
你能想出一个更好的方法来做这样的事吗?
答案 0 :(得分:7)
我怀疑编译器使用了一个稍微误导的检查,看你是否在这里访问一个私有财产
编辑“我们”现在找到了实际来源。出于提供信息的目的,这里有完整的细分,但请随时跳到底部。
(注意应该如何针对Mono编译器提交bug。我认为这个问题会持续一段时间)
'reference'不是有效的命名属性参数。命名属性参数必须是非readonly,static或const的字段,或者不是静态的读写属性。
尝试访问属性类的私有成员。
它似乎它正在使用某种查找(类似于反射)来确保 getter 可访问并且如果结论是必须是私有的。
当然,这不一定是:)
为了好玩,请注意单声道编译器在接受此属性时没有任何问题:https://ideone.com/45fCX
当然可能是编译器要求属性参数具有可反映的值。如果属性不是公开可读的,则只能使用反射来“观察”属性存在,而不是使用它初始化的参数。
我不确切地知道为什么这样的设计选择,但如果考虑到反射的使用,它确实有意义。 < /子>
更新 @Arun发布了确认此推测的相关引文(谢谢!):
<子> 子>
通过反射访问属性一旦属性与程序元素相关联,就可以使用反射来查询它们的存在和值。查询属性的主要反射方法包含在System.Reflection.MemberInfo类(GetCustomAttributes方法系列)中。
原因必须是: 属性参数必须具有可反映的值
奖项问题:这与位置参数有什么关系?如何反映这些?
答案 1 :(得分:3)
This link是来自Visual Studio 2003的引用,但我想它几乎没有改变。
该链接的相关部分:
通过反思访问属性 一旦属性与程序元素相关联,就可以使用反射来查询它们的存在和值。查询属性的主要反射方法包含在System.Reflection.MemberInfo类(GetCustomAttributes方法系列)中。