【问题标题】:What is the "Name=value" in [MyAttribute(Name=value)][MyAttribute(Name=value)] 中的“Name=value”是什么
【发布时间】:2017-02-17 11:58:39
【问题描述】:

我不知道用什么措辞来谷歌这个。

考虑这个属性:

 [MyAttribute(MyOption=true,OtherOption=false)]

Name=value 部分是什么?以及如何在我自己的自定义属性中实现它?

【问题讨论】:

  • 显示(名称="值")?

标签: c# attributes custom-attributes


【解决方案1】:

您可以通过声明公共实例(非静态)属性或字段来使用它:

[AttributeUsage(AttributeTargets.All)]
public class MyAttribute : Attribute
{
    public string TestValue { get; set; }
}

[My(TestValue = "Hello World!")]
public class MyClass{}

所以它的工作方式几乎与对象初始化语法类似,但使用 () 而不是 {}


如果你为你的属性提供了一个带参数的构造函数,你必须先传递参数:

[AttributeUsage(AttributeTargets.All)]
public class MyAttribute : Attribute
{
    public string TestValue { get; set; }

    public MyAttribute(int arg)
    {}
}

[My(42, TestValue = "Hello World!")]
public class MyClass{}

【讨论】:

  • 非常感谢。那怎么能和[MyAttribute("foo",TestValue = "Hello World!"]一起使用呢?
  • 错字:在"Hello World!" 之后,MyAttribute 的两种用法都缺少)
【解决方案2】:

C#规范17.2 Attribute specification

一个属性由一个属性名和一个可选的列表组成 位置命名参数。位置参数(如果有) 在命名参数之前。位置参数由 属性-参数-表达式;命名参数由名称组成, 后跟一个等号,再跟一个 属性-参数-表达式,它们一起受 与简单分配相同的规则。命名参数的顺序不是 意义重大。

所以这里

[MyAttribute(MyOption=true,OtherOption=false)]

你有两个命名参数。什么是命名参数?同样,C# 规范17.3.1 Compilation of an attribute

名称必须标识一个非静态读写公共字段或属性 T(属性类型)。如果 T 没有这样的字段或属性,则编译时错误 发生。

很清楚,我相信。这些名称要么是带有 getter 和 setter 的非静态公共属性(很可能),要么是在 MyAttribute 类中声明的非静态公共字段:

 public class MyAttribute : Attribute
 {
     public bool MyOption { get; set; }
     public bool OtherOption { get; set; }
 }

如果您需要更多命名参数 - 添加另一个具有您要使用的名称的非静态公共读写属性或非静态公共字段。

 public class MyAttribute : Attribute
 {
     public bool MyOption { get; set; }
     public bool OtherOption { get; set; }
     public int Answer { get; set; }
     // public int Answer;  <- another option
 }

用法(顺序无关紧要):

 [MyAttribute(MyOption=true, Answer=42, OtherOption=false)]

【讨论】:

    【解决方案3】:

    它在创建属性实例时指定一个属性。

    属性可以有构造函数参数和属性——这个是设置属性。请注意,您可以混合使用位置构造函数参数、命名构造函数参数和属性,如下面的示例所示:

    using System;
    using System.Linq;
    using System.Reflection;
    
    [AttributeUsage(AttributeTargets.All)]
    public class DemoAttribute : Attribute
    {
        public string Property { get; set; }
        public string Ctor1 { get; set; }
        public string Ctor2 { get; set; }
        public string Ctor3 { get; set; }
    
        public DemoAttribute(string ctor1,
                             string ctor2 = "default2", 
                             string ctor3 = "default3")
        {
            Ctor1 = ctor1;
            Ctor2 = ctor2;
            Ctor3 = ctor3;
        }
    }
    
    [Demo("x", ctor3: "y", Property = "z")]
    public class Test
    {
        static void Main()
        {
            var attr = (DemoAttribute) typeof(Test).GetCustomAttributes(typeof(DemoAttribute)).First();
            Console.WriteLine($"Property: {attr.Property}");
            Console.WriteLine($"Ctor1: {attr.Ctor1}");
            Console.WriteLine($"Ctor2: {attr.Ctor2}");
            Console.WriteLine($"Ctor3: {attr.Ctor3}");
        }
    }
    

    注意: 用于命名构造函数参数和= 用于属性分配之间的区别。

    这段代码的输出是

    Property: z
    Ctor1: x
    Ctor2: default2
    Ctor3: y
    

    不幸的是,在这种情况下,C# 规范同时调用命名构造函数参数和属性“命名参数”:(

    【讨论】:

      【解决方案4】:

      这被称为属性的命名参数。实际上是属性类的属性。更多信息请访问https://msdn.microsoft.com/en-us/library/aa288454(v=vs.71).aspx

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-04-09
        • 2011-06-17
        • 1970-01-01
        • 2012-08-04
        • 1970-01-01
        • 1970-01-01
        • 2018-12-26
        • 1970-01-01
        相关资源
        最近更新 更多