说我有一个类似的枚举:
enum OrderStatus
{
AwaitingAuthorization,
InProduction,
AwaitingDespatch
}
我还在我的枚举上创建了一个扩展方法来整理UI中显示的值,所以我有类似的东西:
public static string ToDisplayString(this OrderStatus status)
{
switch (status)
{
case Status.AwaitingAuthorization:
return "Awaiting Authorization";
case Status.InProduction:
return "Item in Production";
... etc
}
}
受到优秀帖子here的启发,我希望使用扩展方法将我的枚举绑定到SelectList
:
public static SelectList ToSelectList<TEnum>(this TEnum enumObj)
但是,要在UI下拉列表中使用DisplayString值,我需要在
行添加约束。 : where TEnum has extension ToDisplayString
显然,除非有一些我不知道的聪明伎俩,否则这一切都不会对当前的方法起作用。
有没有人对我如何能够实现这样的事情有任何想法?
答案 0 :(得分:27)
在这里使用enum
是否有令人信服的理由?
当你开始跳过疯狂的箍使用enum
时,可能是时候使用一个类了。
public class OrderStatus
{
OrderStatus(string display) { this.display = display; }
string display;
public override string ToString(){ return display; }
public static readonly OrderStatus AwaitingAuthorization
= new OrderStatus("Awaiting Authorization");
public static readonly OrderStatus InProduction
= new OrderStatus("Item in Production");
public static readonly OrderStatus AwaitingDispatch
= new OrderStatus("Awaiting Dispatch");
}
您使用它与enum
:
public void AuthorizeAndSendToProduction(Order order, ProductionQueue queue)
{
if(order.Status != OrderStatus.AwaitingAuthorization)
{
Console.WriteLine("This order is not awaiting authorization!");
return;
}
order.Status = OrderStatus.InProduction;
queue.Enqueue(order);
}
字符串表示是内置的,您只需要ToString()
。
答案 1 :(得分:1)
不要使用“ToDisplayString”,只需覆盖枚举的ToString()。因此,如果枚举覆盖它将接受它,否则它将采用默认的ToString行为(在ToSelectList中)。
答案 2 :(得分:1)
当然,您可以使用DisplayAttribute
来注释您的Enum
。
enum OrderStatus
{
[Display(Description="Long Desc", Name="Awaiting Authorization", ShortName="Wait Auth")]
AwaitingAuthorization,
[Display(Description="...", Name="...", ShortName="...")]
InProduction,
[Display(Description="...", Name="...", ShortName="...")]
AwaitingDespatch
}
您还可以选择创建一个扩展方法,该方法采用任何枚举值并根据为其设置的属性返回其显示名称,以整理UI中显示的值,如下所示:
public static class EnumExtensions
{
public static string ToName(this Enum enumValue)
{
var displayAttribute = enumValue.GetType()
.GetMember(enumValue.ToString())[0]
.GetCustomAttributes(false)
.Select(a => a as DisplayAttribute)
.FirstOrDefault();
return displayAttribute?.Name ?? enumValue.ToString();
}
}
使用
public enum Test
{
[Display(Name="AAA")]
a,
b
}
代码:
Console.WriteLine(Test.a.ToName());
Console.WriteLine(Test.b.ToName());
结果
AAA
b
我想使用扩展方法将枚举绑定到SelectList:
为了类型安全,我不会使用扩展方法,而是使用一个处理Enum类型的静态类:
C#7.3之前的版本。由于Enum
在7.3之前不是有效的类型约束(并且会导致编译时异常),因此您将首先考虑枚举是值类型并且它们实现了一些接口,以便限制键入参数,使其尽可能接近Enum
。
public static class Enums<TEnum> where TEnum : struct, IComparable, IFormattable, IConvertible
{
static Enums()
{
if (!typeof(TEnum).IsEnum)
{
throw new InvalidOperationException();
}
}
}
C#7.3+版本,带有编译时间检查...是的!
public static class Enums<TEnum> where TEnum : Enum
{
}
该类的GetValues方法:
public static IEnumerable<TEnum> GetValues(bool includeFirst)
{
var result = ((TEnum[])Enum.GetValues(typeof(TEnum))).ToList();
if (!includeZero)
result = result.Where(r => r != default).ToList();
return result;
}
如果您遵循Enum Guidelines并包括默认(零)值,我们可以忽略它(有时我们想显示“未选择”之类的值,有时我们不显示“无效选择”)。< / p>
然后我们可以添加另一种方法:
public static IEnumerable<string> GetNames(bool includeFirst)
{
var result = GetValue(includeFirst)
.Select(v => v.ToName())
.ToList();
return result;
}
答案 3 :(得分:0)
如果您只需要使用相对较小的枚举类,这些枚举类只包含一个显式强制转换运算符ToString,并且对nrows
上的枚举及其派生名称空间的特殊使用不具有其他可用性,那么请执行以下操作示例可能是解决方案:
System
答案 4 :(得分:-4)
你可以这样做:
public static string ToOrderStatusDisplayString(this Enum status) { switch ((OrderStatus)status) { ... } }
然后将TEnum限制为枚举:where TEnum : System.Enum
当然,通过这种方式,您可以在Enum上获得一系列方法并失去类型安全性。