我可以使用数组或其他可变数量的参数初始化 C# 属性吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/270187/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 20:55:59  来源:igfitidea点击:

Can I initialize a C# attribute with an array or other variable number of arguments?

c#attributes

提问by

Is it possible to create an attribute that can be initialized with a variable number of arguments?

是否可以创建一个可以用可变数量的参数初始化的属性?

For example:

例如:

[MyCustomAttribute(new int[3,4,5])]  // this doesn't work
public MyClass ...

采纳答案by Mark Brackett

Attributes will take an array. Though if you control the attribute, you can also use paramsinstead (which is nicer to consumers, IMO):

属性将采用一个数组。虽然如果你控制属性,你也可以使用params(这对消费者更好,IMO):

class MyCustomAttribute : Attribute {
    public int[] Values { get; set; }

    public MyCustomAttribute(params int[] values) {
       this.Values = values;
    }
}

[MyCustomAttribute(3, 4, 5)]
class MyClass { }

Your syntax for array creation just happens to be off:

您创建数组的语法恰好关闭:

class MyCustomAttribute : Attribute {
    public int[] Values { get; set; }

    public MyCustomAttribute(int[] values) {
        this.Values = values;
    }
}

[MyCustomAttribute(new int[] { 3, 4, 5 })]
class MyClass { }

回答by Rob Prouse

Yes, but you need to initialize the array that you are passing in. Here is an example from a row test in our unit tests that tests a variable number of command line options;

是的,但您需要初始化您传入的数组。以下是我们单元测试中行测试的示例,该示例测试可变数量的命令行选项;

[Row( new[] { "-l", "/port:13102", "-lfsw" } )]
public void MyTest( string[] args ) { //... }

回答by Jon Skeet

That should be okay. From the spec, section 17.2:

那应该没问题。来自规范第 17.2 节:

An expression E is an attribute-argument-expressionif all of the following statements are true:

如果以下所有语句都为真,则表达式 E 是属性参数表达式

  • The type of E is an attribute parameter type (§17.1.3).
  • At compile-time, the value of E can be resolved to one of the following:
    • A constant value.
    • A System.Type object.
    • A one-dimensional array of attribute-argument-expressions.
  • E 的类型是属性参数类型(第 17.1.3 节)。
  • 在编译时,E 的值可以解析为以下之一:
    • 一个常数值。
    • 一个 System.Type 对象。
    • 属性参数表达式的一维数组。

Here's an example:

下面是一个例子:

using System;

[AttributeUsage(AttributeTargets.All, AllowMultiple = false, Inherited = true)]
public class SampleAttribute : Attribute
{
    public SampleAttribute(int[] foo)
    {
    }
}

[Sample(new int[]{1, 3, 5})]
class Test
{
}

回答by Scott Dorman

Try declaring the constructor like this:

尝试像这样声明构造函数:

public class MyCustomAttribute : Attribute
{
    public MyCustomAttribute(params int[] t)
    {
    }
}

Then you can use it like:

然后你可以像这样使用它:

[MyCustomAttribute(3, 4, 5)]

[MyCustomAttribute(3, 4, 5)]

回答by Alan

You can do that. Another example could be:

你可以这样做。另一个例子可能是:

class MyAttribute: Attribute
{
    public MyAttribute(params object[] args)
    {
    }
}

[MyAttribute("hello", 2, 3.14f)]
class Program
{
    static void Main(string[] args)
    {
    }
}

回答by Marc Gravell

You can do it, but it isn't CLS compliant:

您可以这样做,但它不符合 CLS:

[assembly: CLSCompliant(true)]

class Foo : Attribute
{
    public Foo(string[] vals) { }
}
[Foo(new string[] {"abc","def"})]
static void Bar() {}

Shows:

节目:

Warning 1   Arrays as attribute arguments is not CLS-compliant

For regular reflection usage, it may be preferable to have multiple attributes, i.e.

对于正则反射的使用,最好有多个属性,即

[Foo("abc"), Foo("def")]

However, this won't work with TypeDescriptor/PropertyDescriptor, where only a single instance of any attribute is supported (either the first or last wins, I can't recall which).

但是,这不适用于TypeDescriptor/ PropertyDescriptor,其中仅支持任何属性的单个实例(第一个或最后一个获胜,我不记得是哪个)。

回答by TBrink

To piggy back on Marc Gravell's answer, yes you can define an attribute with array parameters but applying an attribute with an array parameter is not CLS-compliant. However just defining an attribute with an array property is perfectly CLS-compliant.

为了支持 Marc Gravell 的回答,是的,您可以使用数组参数定义属性,但应用具有数组参数的属性不符合 CLS。然而,仅仅用数组属性定义一个属性是完全符合 CLS 的。

What made me realize this was that Json.NET, a CLS-compliant library, has an attribute class JsonPropertyAttribute with a property named ItemConverterParameters that's an array of objects.

让我意识到这一点的是 Json.NET,一个符合 CLS 的库,有一个属性类 JsonPropertyAttribute 和一个名为 ItemConverterParameters 的属性,它是一个对象数组。