是的,你可以得到这个:
BuildCar(Cars.Ferrari.Enzo)
但你不会得到这个:
enum Cars
{
Ford { Corsair, Cortina, Galaxy, GT },
Ferrari { Testarossa, California, Enzo },
...
}
你可以做的是一个带有私有构造函数的密封类,它以一种树结构公开实例,你需要一些帮助类。
以下代码有效:
using System;
namespace _2DEnum
{
public class Example
{
public void BuildCar(Cars car)
{
GC.KeepAlive(car);
}
public void ExampleUse()
{
BuildCar(Cars.Ferrari.Enzo);
}
}
public sealed class Cars
{
private readonly string _value;
private Cars(string value)
{
if (ReferenceEquals(value, null))
{
throw new ArgumentNullException("value");
}
else
{
_value = value;
}
}
public override string ToString()
{
return _value;
}
public static class Ferrari
{
private static readonly Cars _California = new Cars("California");
private static readonly Cars _Enzo = new Cars("Enzo");
private static readonly Cars _Testarossa = new Cars("Testarossa");
public static Cars California
{
get { return Ferrari._California; }
}
public static Cars Enzo
{
get { return Ferrari._Enzo; }
}
public static Cars Testarossa
{
get { return Ferrari._Testarossa; }
}
}
public static class Ford
{
private static readonly Cars _Corsair = new Cars("Corsair");
private static readonly Cars _Cortina = new Cars("Cortina");
private static readonly Cars _Galaxy = new Cars("Galaxy");
private static readonly Cars _GT = new Cars("GT");
public static Cars Corsair
{
get { return Ford._Corsair; }
}
public static Cars Cortina
{
get { return Ford._Cortina; }
}
public static Cars Galaxy
{
get { return Ford._Galaxy; }
}
public static Cars GT
{
get { return Ford._GT; }
}
}
}
}
再说一次,您可以尝试使用一些文本转换模板来像枚举一样键入它。
感谢@ Euphoric ...我需要一个过度分析徽章。
文本转换模板!
我为 T4 创建了一个解决方案,该解决方案使用文件 Enum2D.ttinclude 包含生成此 2D 枚举的代码和每个“2D 枚举”的文件,例如 Cars.tt。
第一个 Enum2D.tt 包括:
<#@ import namespace="System" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #><#+
public string BuildEnum2D
(
string namespaceName,
string enumName,
IEnumerable<Tuple<string, IEnumerable<string>>> items
)
{
string head =
@"
using System;
namespace @namespace
{
public sealed class @enum
{
private readonly string _value;
private @enum(string value)
{
if (ReferenceEquals(value, null))
{
throw new ArgumentNullException(""value"");
}
else
{
_value = value;
}
}
public override string ToString()
{
return _value;
}";
head = head.Replace("@namespace", namespaceName);
head = head.Replace("@enum", enumName);
StringBuilder sb = new StringBuilder();
sb.Append(head);
foreach (var item in items)
{
sb.Append(
@"
public static class " + item.Item1 +
@"
{"
);
foreach (var entry in item.Item2)
{
sb.Append(
@"
private static readonly Cars _" + entry + @" = new Cars(""" + entry +
@""");"
);
}
foreach (var entry in item.Item2)
{
sb.Append(
@"
public static Cars " + entry + @"
{
get { return _" + entry + @"; }
}"
);
}
sb.Append(
@"
}" );
}
sb.Append(
@"
}
}"
);
return "// <auto-generated />" + "\r\n" + sb.ToString();
}
#>
如您所见,该文件定义了一个函数BuildEnum2D
,该函数的唯一目的是在给定参数的情况下为您的 2D 枚举生成代码。现在我们只需要调用它。为此,我们将使用 Cars.tt,如下所示:
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ include file="Enum2D.ttinclude" #>
<#@ output extension=".cs" #><#=
BuildEnum2D
(
"Enum2DTest",
"Cars",
new Tuple<string, IEnumerable<string>>[]
{
new Tuple<string, IEnumerable<string>>
(
"Ferrari",
new string[]
{
"California",
"Enzo",
"Testarossa"
}
),
new Tuple<string, IEnumerable<string>>
(
"Ford",
new string[]
{
"Corsair",
"Cortina",
"Galaxy",
"GT"
}
)
}
)
#>
如您所见,我们包含文件 Enum2D.ttinclude 然后调用函数 Build2DEnum,参数是命名空间、枚举名称和项目。这样,您将能够创建更多这些 2D 枚举,并希望在 tt 文件中维护不会太痛苦。
干杯!