模拟实现接口的枚举的行为

时间:2010-06-09 15:59:55

标签: c# interface enums extension-methods

说我有一个类似的枚举:

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

显然,除非有一些我不知道的聪明伎俩,否则这一切都不会对当前的方法起作用。

有没有人对我如何能够实现这样的事情有任何想法?

5 个答案:

答案 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上获得一系列方法并失去类型安全性。

相关问题