问题:我想使用字符串类型的Enum。
我有一个扩展方法,它根据我的枚举返回字符串值。而且,该扩展还支持注册来自数据库或作为 Web API 输入的新值。
因此,枚举的用例是具有预定义的常量,我可以在代码中针对特定情况使用这些常量。
完整示例请参见:https://dotnetfiddle.net/BFkkd7
var pdf = FileExtensionEnum.PDF;
Console.WriteLine(pdf); //Output: "PDF"
Console.WriteLine(pdf.ToExtensionString()); //Output: ".pdf"
var newExtension = (FileExtensionEnum)10;
Console.WriteLine(newExtension); //Output: 10
Console.WriteLine(newExtension.ToExtensionString()); //Output: "10"
var registeredFile = ".png".FromStringExtension();
Console.WriteLine(registeredFile); //Output: 4
Console.WriteLine(registeredFile.ToExtensionString()); //Output: ".png"
但是,在调试器中它看起来像这样:
newExtension 变量保存值“10”,并将显示为 10,因为它是 FileExtensionEnum 的未知值,并且对于我的扩展方法来说也是未知值。
registeredFile 值对于 FileExtensionEnum 未知,将显示为 4,但我的扩展程序会将其显示为 ".png"
剩下的部分是使用我的扩展方法强制调试器显示FileExtensionEnum。因此,它将始终显示为字符串。
下面是我尝试为 Visual Studio 2022 做的事情。
[DebuggerDisplay("Value = {this.ToExtensionString()}")]
[DebuggerDisplay("Value = {EnumToString.EnumStringExtension.ToExtensionString(this)}")]
[DebuggerDisplay("Value = {this}")]
[DebuggerDisplay("Value = {GetValue()}")]
[assembly: DebuggerDisplay("Value = {EnumToString.EnumStringExtension.ToExtensionString(this)}", Target = typeof(EnumToString.FileExtensionEnum))]
// result
pdf Value = <Internal Error evaluating expression> EnumToString.FileExtensionEnum
public class EnumStringDebugView
{
private readonly FileExtensionEnum value;
public EnumStringDebugView(FileExtensionEnum value) => this.value = value;
public override string ToString() => value.ToExtensionString();
}
// Compilation time error:
// CS0592 Attribute 'DebuggerTypeProxy' is not valid on this declaration type. It is only valid on 'assembly, class, struct' declarations.
[DebuggerTypeProxy(typeof(EnumStringDebugView))]
public enum FileExtensionEnum
// Does not fail, but just ignored
[assembly: DebuggerTypeProxy(typeof(EnumToString.EnumStringDebugView), Target = typeof(EnumToString.FileExtensionEnum))]
public class SampleStringCode
{
private string readonly _value;
private SampleStringCode(string value) => this._value = value;
public static readonly SampleStringCode S1 = new("S1");
public static readonly SampleStringCode S2 = new("S2");
public static readonly SampleStringCode S3 = new("S3");
}
public static class FileExtenions
{
public const string EXCEL = ".excel";
public const string PDF = ".pdf";
public const string JPG = ".jpg";
}
然后我们可以拥有一个可以应用于字符串属性或字符串参数的自定义属性。
public class Document
{
[UseConst(typeof(FileExtenions))]
public string Extension { get; set; }
}
然后实现一个自定义代码分析器,它基于属性限制您将任何字符串分配给属性,除了来自 FileExtenions 类的常量。
我并没有尝试这样做,但听起来有点矫枉过正。但就代码简单性而言,这将是最好的。无需编写额外的代码,无需编写自定义 EF 转换器或 JSON 转换器或 API 的 ModelBinding。但你必须使用自定义属性。
在枚举的编译版本中,私有字段“value__”保存数值。您可以使用它来显示数值,如下所示:
[DebuggerDisplay("Value: {value__}")]
enum Foo { Bar = -1, Baz=1 }
或者简单地
[DebuggerDisplay("{value__}")]
enum Foo { Bar = -1, Baz=1 }
在 vs2019 和 vs2022 的各种框架上进行了测试