本文介绍如何使用枚举以及,如何将枚举类型更好的应用于项目中,看完本文可以有序的将项目中的枚举更容易的使用到每个角落。
1,分析枚举
/// <summary>
/// 性别
/// </summary>
public enum Gender
{
/// <summary>
/// 男
/// </summary>
Man = 0,
/// <summary>
/// 女
/// </summary>
Women = 1
}
如1所示,这是一个非常普通的枚举类,在项目中使用的话,一般都会将它作为某实体的一个属性,这个时候问题就来了,在页面里边我们是需要拿到与之相关的描述信息和对应的值作为一个下拉框或者checkbox让用户去选择,同时也不可以将Disable和enable作为给用户最终展示的信息,需要去手动去拼,于是有了如下的方式
2,枚举类信息完善,增加描述信息
/// <summary>
/// 性别
/// </summary>
public enum Gender
{
/// <summary>
/// 男
/// </summary>
[Description("男")]
Man = 0,
/// <summary>
/// 女
/// </summary>
[Description("女")]
Women = 1
}
再给枚举增加一个扩展方法
/// <summary>
/// 获取到对应枚举的描述-没有描述信息,返回枚举值
/// </summary>
/// <param name="enum"></param>
/// <returns></returns>
public static string GetDescription(this Enum @enum)
{
Type type = @enum.GetType();
string name = Enum.GetName(type, @enum);
if (name == null)
{
return null;
}
FieldInfo field = type.GetField(name);
if (!(Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) is DescriptionAttribute attribute))
{
return name;
}
return attribute?.Description;
}
好像到这一步的时候问题可以得到解决,通过getdescroption()这类的方法可以去获取到与枚举相应的描述信息用于展示,但是这也仅限于在mvc模式下,通过viewbag将枚举的类中的每一项都加到枚举集合中返回给页面,在页面里边遍历,如果枚举类型很多,那么这类型的重复逻辑就会很多,非常的心烦。
如果可以将这些操作做一个封装,用一个接口可以返回所有枚举类型的相关信息,就好了,于是有了如下的做法
1 创建一个描述枚举的类
public class EnumModel
{
/// <summary>
///枚举原始值
/// </summary>
public ValueType Source { get; set; }
/// <summary>
/// 描述信息
/// </summary>
public string Description { get; set; }
/// <summary>
/// value
/// </summary>
public int Value { get; set; }
}
2,写一个方法通过传递一个枚举类类型去得到List<EnumModel>
public static List<EnumModel> GetEnumListModels<T>()
{
var model = default(T);
FieldInfo[] fieldinfo = typeof(T).GetFields();
List<EnumModel> result = new List<EnumModel>();
foreach (FieldInfo field in fieldinfo)
{
EnumModel enumModel = new EnumModel();
if (!(Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) is DescriptionAttribute attribute))
{
enumModel.Description = field.GetValue(model).ToString();
}
else
{
enumModel.Description = attribute.Description;
}
enumModel.Value = field.GetValue(model).GetHashCode();
enumModel.Source = field.GetValue(model) as ValueType;
if (field.GetValue(model).ToString() != "0")
{
result.Add(enumModel);
}
}
return result;
}
3,写一个接口,输入枚举的类的名称,调用2中的方法,得到具体的返回信息
[Route("[controller]/{name}")]
public IActionResult GetEnumList(string name)
{
Assembly assembly = Assembly.Load("Ftw");
Type t = assembly.GetType(string.Concat("Ftw.Enum.", name), throwOnError: false, ignoreCase: true);
if (t == null)
{
throw new ServiceException(string.Concat("请确保枚举[", name, "]在 Ftw.Enum 中定义"));
}
Type enumhelp = typeof(EnumHelper);
var obj = enumhelp.GetMethod("GetEnumListModels").MakeGenericMethod(t);
return Json(obj.Invoke(t, null));
}
解释一下:Ftw是类库的名称,Enum是Ftw类库下的一个文件夹,所有的枚举类都在Enum下边放着,EnumHelper是 2 中方法【GetEnumListModels】所在的类,通过反射程序集得到枚举类型,通过反射程序集将类型传入GetEnumListModels作为 T 最后执行方法的到list.
比如 Gender的调用,假如 GetEnumList所在的controller是EnumController,那么调用就是通过 Enum/Gender ,对于.net core, mvc .net core api这类项目这种方式是非常有帮助的。