簡體   English   中英

如何聲明值為字符串數組的 DefaultValue 屬性?

[英]How do I declare a DefaultValue attribute whose value is an array of strings?

我一直在代碼生成器中使用 DefaultValue 屬性,它從架構中編寫 C# 類定義。

我被困在架構中的屬性是一個字符串數組的地方。

我想在我的 C# 中寫這樣的東西:

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

但這不會編譯。

有什么方法可以成功聲明字符串數組的默認值屬性嗎?

你可以試試

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

當你想傳遞一個新的字符串數組時,你必須實例化它——這是由new string[] C# 允許帶有數組初始內容的初始化列表緊跟在大括號中,即{ "a", "b" }


編輯:正如Cory-G正確指出的那樣,您可能希望確保您的實際實例不會收到存儲在DefaultValue屬性中的數組實例。 否則,對該實例的更改可能會影響整個應用程序的默認值。

相反,您可以使用屬性的 setter 來復制分配的數組。

另一種解決方案是利用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 不會經常被調用,但默認比較會。

同樣,只需確保您對如何使用該屬性有所了解。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM