我可以为属性使用集合初始值设定项吗?

Sco*_*pey 6 c# attributes custom-attributes object-initializers collection-initializer

C#中的属性可以与集合初始值设定项一起使用吗?

例如,我想做类似以下的事情:

[DictionaryAttribute(){{"Key", "Value"}, {"Key", "Value"}}]
public class Foo { ... }
Run Code Online (Sandbox Code Playgroud)

我知道属性可以有命名参数,因为这看起来与对象初始化器非常相似,我想知道集合初始化器是否也可用.

vla*_*mir 6

更新:对不起我错了 - 传递自定义类型的数组是不可能的:(

属性类的位置和命名参数的类型仅限于属性参数类型,它们是:

  1. 以下类型之一:bool,byte,char,double,float,int,long,short,string.
  2. 类型对象.
  3. 类型System.Type.
  4. Enum类型,前提是它具有公共可访问性,并且嵌套类型(如果有)也具有公共可访问性(第17.2节).
  5. 上述类型的一维阵列. 资源

来源:stackoverflow.

您可以DECLARE传递自定义类型的数组:

class TestType
{
  public int Id { get; set; }
  public string Value { get; set; }

  public TestType(int id, string value)
  {
    Id = id;
    Value = value;
  }
}

class TestAttribute : Attribute
{
  public TestAttribute(params TestType[] array)
  {
    //
  }
}
Run Code Online (Sandbox Code Playgroud)

但属性声明上发生编译错误:

[Test(new[]{new TestType(1, "1"), new TestType(2, "2"), })]
public void Test()
{

}
Run Code Online (Sandbox Code Playgroud)


Mic*_*ays 5

C#4.0规范的第17.1.3节特别不允许在属性参数内部使用多维数组,因此虽然Foo(string [,] bar)可能允许您调用Foo(new [,] {{"a","b "},{"key2","val2"}}),遗憾的是,它不适用于属性.

因此,考虑到这一点,有几种可能性来近似你想要的东西:

  1. 使用具有交替键和值对的一维数组.这种方法的明显缺点是它并没有完全强制执行名称和值.

  2. 通过使用以下属性标记属性定义,允许您的参数多次出现:

    [AttributeUsage(AllowMultiple=true)]
    
    Run Code Online (Sandbox Code Playgroud)

    通过这种方式,您现在可以定义:

    [KeyVal("key1","val1"), KeyVal("key2","val2")]
    public class Foo { ... }
    
    Run Code Online (Sandbox Code Playgroud)

    这比我确定你所希望的更有讽刺,但它在名称和价值观之间做了明确的界定.

  3. 查找JSON包并为您的属性提供初始化程序.性能损失是无关紧要的,因为这是在代码初始化期间完成的.例如,使用Newtonsoft.Json,你可以创建一个如下属性:

        public class JsonAttribute : Attribute
        {
          Dictionary<string, string> _nameValues = 
              new Dictionary<string, string>();
          public JsonAttribute(string jsoninit)
          {
            var dictionary = new Dictionary<string, string>();
            dynamic obj = JsonConvert.DeserializeObject(jsoninit);
            foreach(var item in obj)
              _nameValues[item.Name] = item.Value.Value;
          }
        }
    
    Run Code Online (Sandbox Code Playgroud)

    然后,这将允许您实例化一个属性,如下所示:

    [Json(@"{""key1"":""val1"", ""key2"":""val2""}")]
    public class Foo { ... }
    
    Run Code Online (Sandbox Code Playgroud)

    我知道这有点引用 - 很高兴,更多涉及,但你有.无论如何,在这个疯狂的动态世界中,知道如何使用JSON初始化对象并不是一个糟糕的技能.