众所周知,我们在使用枚举时,可以很轻松的获取枚举的名称和值:

public enum EnumOrderStatus
{
    待制作 = 1,
    制作中 = 2,
    待发货 = 3,
    待收货确认 = 4,
    确认收货 = 5,
    交易完成 = 6,
    交易关闭 = 0
}
var needProduce = EnumOrderStatus.待制作;
var name = needProduce.ToString(); //获取枚举的名称:name = "待制作"
var value = (int)needProduce;//获取枚举的值:value = 1;

枚举的常用方法如上。


在某项目中遇到业务场景如下:订单表中用一个OrderStatus记录了订单状态的枚举名称,需要在页面中呈现如下的订单进度,这下int类型的枚举值就不适用了,因为进度中的百分比中存在小数位。

1.根据订单状态枚举显示订单进度.jpg


这时可使用Attribute特性类扩展枚举,具体用法如下:


1. 创建一个特性类,继承System.Attribute

/// <summary>
/// 订单进度百分比数值
/// </summary>
[AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = false)]
public class Progress : System.Attribute
{
    //进度值
    public float ProgressValue { get; set; }
    public Progress(float progress)
    {
        ProgressValue = progress;
    }
}


2. 在创建枚举的地方,为每个枚举值附上特性值

public enum EnumOrderStatus
{
    [Progress(25f)]
    待制作 = 1,
    
    [Progress(25f * 2)]
    制作中 = 2,
    
    [Progress(25f * 3)]
    待发货 = 3,
    
    [Progress(25f * 3 + 12.5f)]
    待收货确认 = 4,
    
    [Progress(100f)]
    确认收货 = 5,
    
    [Progress(100f)]
    交易完成 = 6,
    
    [Progress(100f)]
    交易关闭 = 0
}


3. 创建特性类取值方法,此处为了调用方便,用的是扩展方法

/// <summary>
/// 获取订单状态的百分比进度
/// </summary>
/// <param name="status">传入枚举名称</param>
/// <returns></returns>
public static float GetOrderProgress(this string status)
{
    var type = typeof(EnumOrderStatus);
    var mInfo = type.GetMembers().FirstOrDefault(p => string.Equals(p.Name, status, StringComparison.OrdinalIgnoreCase));
    if (mInfo == null)
        return 0f;
        
    var attr = Attribute.GetCustomAttribute(mInfo, typeof(Progress));
    if (attr == null)
        return 0f;
        
    return ((Progress)attr).ProgressValue;
}


4. 获取枚举的特性值:

//var orderInfo = OrderService.Get(orderId);
//var progress = orderInfo.OrderStatus.GetOrderProgress();

var progress = "待制作".GetOrderProgress();
Response.Write(progress); //输出25.0