如何声明其值为字符串数组的DefaultValue属性?

时间:2012-09-18 14:17:17

标签: c# .net attributes default-value

我一直在代码生成器中使用DefaultValue属性,该代码生成器从模式中编写C#类定义。

我遇到架构中的属性是字符串数组的地方。

我想在我的C#中写下这样的东西:

[DefaultValue(typeof(string[]), ["a","b"])]
public string[] Names{get;set;}

但不会编译。

有什么方法可以成功声明字符串数组的默认值属性吗?

2 个答案:

答案 0 :(得分:9)

你可以尝试

[DefaultValue(new string[] { "a", "b" })]

由于你想传​​递一个新的字符串数组,你必须实例化它 - 这是由new string[]完成的。 C#允许一个初始化列表,其中数组的初始内容遵循大括号,即{ "a", "b" }

答案 1 :(得分:0)

另一种解决方案是利用 DefaultValueAttribute 的虚拟性质并派生自己的。下面是一些具有非常量类型的示例。

示例用法:

public class Foo
{
    [DefaultValueNew( typeof(List<int>), new int[]{2,2} )]
    public List<int> SomeList { get; set; }

    // -- Or --
    public static List<int> GetDefaultSomeList2() => new List<int>{2,2};

    [DefaultValueCallStatic( typeof(Foo), nameof(GetDefaultSomeList2) )]
    public List<int> SomeList2 { get; set; }
};

以下是这些属性的定义:

  public class DefaultValueNewAttribute : DefaultValueAttribute
  {
    public Type Type { get; }
    public object[] Args { get; }

    public DefaultValueNewAttribute(Type type, params object[] args)
      : base(null)
    {
      Type = type;
      Args = args;
    }

    public override object? Value => Activator.CreateInstance(Type, Args);
  };

  public class DefaultValueCallStaticAttribute : DefaultValueAttribute
  {
    public Type Type { get; }
    public string Method { get; }

    public DefaultValueCallStaticAttribute(Type type, string method)
      : base(null)
    {
      Type = type;
      Method = method;
    }

    public override object? Value => Type.GetMethod(Method, BindingFlags.Public | BindingFlags.Static).Invoke(null, null);
  };

需要注意的问题

定义自己的 DefaultValueAttribute 时要小心。最重要的是,在创建它之前先了解一下它将如何使用。对于代码生成器之类的东西,上面的内容可能没问题。但是,如果您将它与 Newtonsoft Json 或主要仅用于比较值的东西一起使用,那么您可能希望其中的值更加恒定,以节省时间而不是每次都重新创建对象。

对于不希望每次都重新创建值的情况,您可以执行以下操作:

  public static readonly List<int> DefaultAges = new List<int>{2,2};
  private List<int> __ages = new List<int>(DefaultAges);
  [DefaultValueStatic( typeof(List<int>), nameof(DefaultAges) )]
  public List<int> Ages { get => __ages; set {__ages = new List<int>(value);}

其中属性 DefaultValueStatic 定义为:

  public class DefaultValueStaticAttribute : DefaultValueAttribute
  {
    public DefaultValueStaticAttribute(Type type, string memberName) : base(null)
    {
      foreach (var member in type.GetMember( memberName, BindingFlags.Static | BindingFlags.Public ))
      {
        if (member is FieldInfo fi) { SetValue(fi.GetValue(type)); return; }
        if (member is PropertyInfo pi) { SetValue(pi.GetValue(type)); return; }
      }
      throw new ArgumentException($"Unable to get static member '{memberName}' from type '{type.Name}'");
    }
  };

以上版本将确保不会重新创建默认值。这对于 Newtonsoft json 之类的东西很有用,其中 setter 不会经常被调用,但默认比较会。

同样,只需确保您对如何使用该属性有所了解即可。