【问题标题】:How to pass objects into an attribute constructor如何将对象传递给属性构造函数
【发布时间】:2010-11-17 03:54:15
【问题描述】:

我正在尝试将对象传递给 Attributes 构造函数,如下所示:

[PropertyValidation(new NullOrEmptyValidatorScheme())]
public string Name { get; private set; }

有了这个属性构造函数:

 public PropertyValidationAttribute(IValidatorScheme validator) {
      this._ValidatorScheme = validator;
    }

代码无法编译。如上所述,如何将对象传递给属性?

编辑:是的 NullOrEmptyValidatorScheme 实现了 IValidatorScheme。

错误:错误CS0182:属性参数必须是属性参数类型的常量表达式、typeof表达式或数组创建表达式。

【问题讨论】:

  • 什么是编译错误?你确定NullOrEmptyValidatorScheme 实现了IValidatorScheme
  • 就属性语法而言,这是有效的代码,因此它必须与您的对象有关。
  • @kek444 - 不,不是...我将规范部分添加到我的回复中...

标签: c# attributes


【解决方案1】:

属性中的值仅限于简单类型;例如,基本常量(包括字符串)和typeof... 不能使用new 或其他更复杂的代码。简而言之;你不能这样做。你可以给它type

[PropertyValidation(typeof(NullOrEmptyValidatorScheme)]

PropertyValidation ctor 采用 Type,并在代码中使用 Activator.CreateInstance 来创建对象。请注意,理想情况下,您应该只在内部存储字符串 (AssemblyQualifiedName)。

来自 ECMA 334v4:

§24.1.3 属性参数类型

位置和命名的类型 属性类的参数是 仅限于 attribute 参数 类型,分别是:

  • 以下类型之一:boolbytechardoublefloatintlongshortstring
  • 类型object
  • 类型System.Type
  • 枚举类型,只要它具有公共可访问性和 嵌套的类型(如果有) 还具有公共可访问性。
  • 上述的一维数组 类型。

§24.2 属性规范

...

表达式E 是 属性参数表达式如果全部 以下陈述中的一个是正确的:

  • E 的类型是一个属性 参数类型(第 24.1.3 节)。
  • 在编译时,E 的值可以是 解决以下问题之一:
    • 一个常数值。
    • 指定非泛型的表达式类型 (§14.5.11) 类型,一个封闭的构造类型 (§25.5.2),或未绑定的泛型类型 (§25.5)。
    • 一维数组 属性参数表达式。

【讨论】:

  • 这是对枚举值之一的第二次引用,但实现起来并非易事。你知道使用枚举的任何示例实现吗?
  • @QueueHammer [DefaultValue(AnyEnum.SomeValue)] 就足够了;否则,类似[System.Xml.Serialization.XmlElement(Form = System.Xml.Schema.XmlSchemaForm.Qualified)]
【解决方案2】:

正如之前的海报所指出的,属性参数中使用的类型受到了相当严格的限制(可以理解,因为它们的值需要直接序列化到程序集元数据 blob 中)。

也就是说,您可能可以创建一个利用 typeofs 的解决方案,因为这些 可以 使用。

例如:

[PropertyValidation(typeof(NullOrEmptyValidatorScheme))]
public string Name { get; private set; }

这种语法是完全合法的。读取您必须获取验证器类型的属性的代码,创建验证器的新实例(如果合适,它甚至可以维护以验证器类型为键的验证器缓存 - 这是一种相当常见的技术),然后调用它.

【讨论】:

  • 感谢您的回答。我已经给了马克接受的答案。但是您使用缓存的建议很有帮助,并且设想这样做是为了避免许多 Activator.CreateInstance 调用。
【解决方案3】:

还有……(我认为是微软的Bug)

您不能将默认值设置为“null”,但默认的简单默认值可以('false'、'7'、'"Test")。

下一个例子会给你以下错误: 属性参数必须是属性参数类型的常量表达式、typeof 表达式或数组创建表达式
在文件中:... \CSC

public class SampleAttribute : Attribute
{
    private string _test;
    public SampleAttribute(string test = null)
    {
        _test = test;
    }
}

[Sample]
public class Toto
{

}

【讨论】:

  • 可能与:“属性和命名/可选构造函数参数不起作用”stackoverflow.com/q/8189807/276648
  • 对于user276648,我认为您是对的,它们是相关的,并且那里的解决方案似乎更完整。谢谢!
  • 实际上,对于您的示例,它可能与编译器错误有关(意味着您编写的内容在 Mono 编译时可能有效)stackoverflow.com/q/8290853
猜你喜欢
  • 2013-09-13
  • 1970-01-01
  • 2014-06-04
  • 1970-01-01
  • 2016-10-12
  • 1970-01-01
  • 1970-01-01
  • 2021-06-30
  • 2017-03-17
相关资源
最近更新 更多