C# 带有整数字符串的枚举
我有一个公共的C# 带有整数字符串的枚举,c#,asp.net,asp.net-mvc,C#,Asp.net,Asp.net Mvc,我有一个公共的enum如下: public enum occupancyTimeline { TwelveMonths, FourteenMonths, SixteenMonths, EighteenMonths } 我将使用它作为下拉菜单,如下所示: @Html.DropDownListFor(model => model.occupancyTimeline, new SelectList(Enum.GetValues(typeof(Centra
enum
如下:
public enum occupancyTimeline
{
TwelveMonths,
FourteenMonths,
SixteenMonths,
EighteenMonths
}
我将使用它作为下拉菜单,如下所示:
@Html.DropDownListFor(model => model.occupancyTimeline,
new SelectList(Enum.GetValues(typeof(CentralParkLCPreview.Models.occupancyTimeline))), "")
现在我正在寻找这样的价值观
12个月、14个月、16个月、18个月,而不是二十个月、十四个月、十六个月、十八个月
我将如何做到这一点
public enum occupancyTimeline
{
TwelveMonths=0,
FourteenMonths=1,
SixteenMonths=2,
EighteenMonths=3
}
public string[] enumString = {
"12 Months", "14 Months", "16 Months", "18 Months"};
string selectedEnum = enumString[(int)occupancyTimeLine.TwelveMonths];
或
我为自己制作了一种扩展方法,现在我在每个项目中都使用这种方法:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Web.Mvc;
namespace App.Extensions
{
public static class EnumExtensions
{
public static SelectList ToSelectList(Type enumType)
{
return new SelectList(ToSelectListItems(enumType));
}
public static List<SelectListItem> ToSelectListItems(Type enumType, Func<object, bool> itemSelectedAction = null)
{
var arr = Enum.GetValues(enumType);
return (from object item in arr
select new SelectListItem
{
Text = ((Enum)item).GetDescriptionEx(typeof(MyResources)),
Value = ((int)item).ToString(),
Selected = itemSelectedAction != null && itemSelectedAction(item)
}).ToList();
}
public static string GetDescriptionEx(this Enum @this)
{
return GetDescriptionEx(@this, null);
}
public static string GetDescriptionEx(this Enum @this, Type resObjectType)
{
// If no DescriptionAttribute is present, set string with following name
// "Enum_<EnumType>_<EnumValue>" to be the default value.
// Could also make some code to load value from resource.
var defaultResult = $"Enum_{@this.GetType().Name}_{@this}";
var fi = @this.GetType().GetField(@this.ToString());
if (fi == null)
return defaultResult;
var customAttributes = fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
if (customAttributes.Length <= 0 || customAttributes.IsNot<DescriptionAttribute[]>())
{
if (resObjectType == null)
return defaultResult;
var res = GetFromResource(defaultResult, resObjectType);
return res ?? defaultResult;
}
var attributes = (DescriptionAttribute[])customAttributes;
var result = attributes.Length > 0 ? attributes[0].Description : defaultResult;
return result ?? defaultResult;
}
public static string GetFromResource(string defaultResult, Type resObjectType)
{
var searchingPropName = defaultResult;
var props = resObjectType.GetProperties();
var prop = props.FirstOrDefault(t => t.Name.Equals(searchingPropName, StringComparison.InvariantCultureIgnoreCase));
if (prop == null)
return defaultResult;
var res = prop.GetValue(resObjectType) as string;
return res;
}
public static bool IsNot<T>(this object @this)
{
return !(@this is T);
}
}
}
更新
根据Phil的建议,我已经更新了上面的代码,可以从一些资源(如果您有)中读取enum的显示值。资源中项目的名称应采用Enum\uuuu
的形式(例如Enum\u occumencytimeline\u十二个月
)。通过这种方式,您可以在资源文件中为枚举值提供文本,而无需使用某些属性修饰枚举值。资源类型(MyResource)直接包含在ToSelectItems方法中。您可以将其提取为扩展方法的参数
命名枚举值的另一种方法是应用Description属性(这种方法不需要使代码适应我所做的更改)。例如:
public enum occupancyTimeline
{
[Description("12 Months")]
TwelveMonths,
[Description("14 Months")]
FourteenMonths,
[Description("16 Months")]
SixteenMonths,
[Description("18 Months")]
EighteenMonths
}
对枚举进行扩展描述
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.ComponentModel;
public static class EnumerationExtensions
{
//This procedure gets the <Description> attribute of an enum constant, if any.
//Otherwise, it gets the string name of then enum member.
[Extension()]
public static string Description(Enum EnumConstant)
{
Reflection.FieldInfo fi = EnumConstant.GetType().GetField(EnumConstant.ToString());
DescriptionAttribute[] attr = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
if (attr.Length > 0) {
return attr(0).Description;
} else {
return EnumConstant.ToString();
}
}
}
使用系统;
使用系统集合;
使用System.Collections.Generic;
使用系统数据;
使用系统诊断;
使用System.Runtime.CompilerServices;
使用系统组件模型;
公共静态类枚举扩展
{
//此过程获取枚举常量(如果有)的属性。
//否则,它将获取枚举成员的字符串名称。
[扩展名()]
公共静态字符串描述(枚举常量)
{
Reflection.FieldInfo fi=EnumConstant.GetType().GetField(EnumConstant.ToString());
DescriptionAttribute[]attr=(DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute),false);
如果(属性长度>0){
返回属性(0)。说明;
}否则{
返回EnumConstant.ToString();
}
}
}
除了使用属性进行描述(请参阅其他答案或使用谷歌),我经常使用RESX文件,其中键是枚举文本(例如,十二个月
),值是所需的文本
然后,执行一个返回所需文本的函数是相对简单的,而且为多语言应用程序翻译值也很容易
我还想添加一些单元测试,以确保所有值都有关联的文本。如果有一些异常(比如最后的Count
值),那么单元测试将从检查中排除这些异常
所有这些都不是很难,也不是很灵活。如果您使用DescriptionAttribute
并希望获得多语言支持,那么您仍然需要使用资源文件
通常,我会有一个类来获取每个enum
类型需要显示的值(显示的名称),每个资源文件有一个单元测试文件,尽管我还有一些其他类用于一些常见代码,比如比较资源文件中的键和单元测试的enum
中的值(一个重载允许指定异常)
顺便说一句,在这种情况下,让枚举的值与月数匹配(例如twevemonths=12
)是有意义的。在这种情况下,您还可以使用string.Format
来显示值,并且资源中也有异常(如单数).您可以用于此目的。以下是您想要的示例。(不要忘记使用EnumDropDownList for
您应该使用ASP MVC 5和Visual Studio 2015。):
你的看法:
@using System.Web.Mvc.Html
@using WebApplication2.Models
@model WebApplication2.Models.MyClass
@{
ViewBag.Title = "Index";
}
@Html.EnumDropDownListFor(model => model.occupancyTimeline)
还有你的模特:
public enum occupancyTimeline
{
[Display(Name = "12 months")]
TwelveMonths,
[Display(Name = "14 months")]
FourteenMonths,
[Display(Name = "16 months")]
SixteenMonths,
[Display(Name = "18 months")]
EighteenMonths
}
参考资料:MVC 5.1
@Html.EnumDropDownListFor(model => model.MyEnum)
MVC 5
@Html.DropDownList("MyType",
EnumHelper.GetSelectList(typeof(MyType)) ,
"Select My Type",
new { @class = "form-control" })
MVC 4
你可以参考这个链接
用法
你可以看看这个
他的解决方案是针对Asp.NET的,但是通过简单的修改,你可以像MVC一样使用它
/// <span class="code-SummaryComment"><summary></span>
/// Provides a description for an enumerated type.
/// <span class="code-SummaryComment"></summary></span>
[AttributeUsage(AttributeTargets.Enum | AttributeTargets.Field,
AllowMultiple = false)]
public sealed class EnumDescriptionAttribute : Attribute
{
private string description;
/// <span class="code-SummaryComment"><summary></span>
/// Gets the description stored in this attribute.
/// <span class="code-SummaryComment"></summary></span>
/// <span class="code-SummaryComment"><value>The description stored in the attribute.</value></span>
public string Description
{
get
{
return this.description;
}
}
/// <span class="code-SummaryComment"><summary></span>
/// Initializes a new instance of the
/// <span class="code-SummaryComment"><see cref="EnumDescriptionAttribute"/> class.</span>
/// <span class="code-SummaryComment"></summary></span>
/// <span class="code-SummaryComment"><param name="description">The description to store in this attribute.</span>
/// <span class="code-SummaryComment"></param></span>
public EnumDescriptionAttribute(string description)
: base()
{
this.description = description;
}
}
您可以在控制器中使用它来填充下拉列表,如下所示:
ViewBag.occupancyTimeline =new SelectList( EnumHelper.ToList(typeof(occupancyTimeline)),"Value","Key");
在您看来,您可以使用以下
@Html.DropdownList("occupancyTimeline")
希望它能帮助您发布解决方案的模板,您可以根据需要更改某些部分
定义用于格式化枚举的通用EnumHelper:
public abstract class EnumHelper<T> where T : struct
{
static T[] _valuesCache = (T[])Enum.GetValues(typeof(T));
public virtual string GetEnumName()
{
return GetType().Name;
}
public static T[] GetValuesS()
{
return _valuesCache;
}
public T[] GetValues()
{
return _valuesCache;
}
virtual public string EnumToString(T value)
{
return value.ToString();
}
}
我会选择一种稍有不同且可能更简单的方法:
public static List<int> PermittedMonths = new List<int>{12, 14, 16, 18};
以您描述的方式使用枚举可能有点麻烦。您可以将getter强制转换为整数,而不是尝试从枚举
在视图中绘制属性。我的问题是,我将枚举的值编写为字符串,但我希望使用它的int值
例如,在视图模型类中可以有以下两个属性:
public enum SomeEnum
{
Test = 0,
Test1 = 1,
Test2,
}
public SomeEnum SomeEnum {get; init;}
public int SomeEnumId => (int) SomeEnum;
然后,您可以通过razor视图访问您的enum
,如下所示:
<input type="hidden" asp-for="@Model.SomeEntityId" />
您的意思是显示在您的下拉菜单中?显示在下拉菜单中并作为其值。幸运的是,没有设置枚举.ToString()
函数的事情,我相信。您有没有看过这个问题?我会用字典替换您的字符串[]
枚举字符串:更易于维护(例如,如果您将枚举定义移动到另一个文件中)对我来说,这似乎是一个很好的答案,但缺少一些关键信息。如何指定与枚举值关联的自定义文本?更新了我的答案。希望能有所帮助。我收到了一个错误,它是var defaultResult=$“enum{@this.GetType().Name}{@this}”
$”字符串插值是在C#6.0(Visual studio 2015)中首次引入的。如果它不起作用,您可以使用string.Format。鉴于问题是在C#中提出的,您应该在C#中回答,或者至少告诉我们它是VB.NET,可以(轻松)转换,以便我们知道您知道。我得到一个错误…@Html.DropDownListFor(model=>model.OccupncyTimeLine,model.OccupncyTimeLine.ToSelectList());
:“string”不包含“ToSelectList”的定义,并且没有扩展方法“ToSelectList”接受第一个
ViewBag.occupancyTimeline =new SelectList( EnumHelper.ToList(typeof(occupancyTimeline)),"Value","Key");
@Html.DropdownList("occupancyTimeline")
public abstract class EnumHelper<T> where T : struct
{
static T[] _valuesCache = (T[])Enum.GetValues(typeof(T));
public virtual string GetEnumName()
{
return GetType().Name;
}
public static T[] GetValuesS()
{
return _valuesCache;
}
public T[] GetValues()
{
return _valuesCache;
}
virtual public string EnumToString(T value)
{
return value.ToString();
}
}
public static class SystemExt
{
public static MvcHtmlString DropDownListT<T>(this HtmlHelper htmlHelper,
string name,
EnumHelper<T> enumHelper,
string value = null,
string nonSelected = null,
IDictionary<string, object> htmlAttributes = null)
where T : struct
{
List<SelectListItem> items = new List<SelectListItem>();
if (nonSelected != null)
{
items.Add(new SelectListItem()
{
Text = nonSelected,
Selected = string.IsNullOrEmpty(value),
});
}
foreach (T item in enumHelper.GetValues())
{
if (enumHelper.EnumToIndex(item) >= 0)
items.Add(new SelectListItem()
{
Text = enumHelper.EnumToString(item),
Value = item.ToString(), //enumHelper.Unbox(item).ToString()
Selected = value == item.ToString(),
});
}
return htmlHelper.DropDownList(name, items, htmlAttributes);
}
}
public class OccupancyTimelineHelper : EnumHelper<OccupancyTimeline>
{
public override string EnumToString(occupancyTimeline value)
{
switch (value)
{
case OccupancyTimelineHelper.TwelveMonths:
return "12 Month";
case OccupancyTimelineHelper.FourteenMonths:
return "14 Month";
case OccupancyTimelineHelper.SixteenMonths:
return "16 Month";
case OccupancyTimelineHelper.EighteenMonths:
return "18 Month";
default:
return base.EnumToString(value);
}
}
}
@Html.DropDownListT("occupancyTimeline", new OccupancyTimelineHelper())
public static List<int> PermittedMonths = new List<int>{12, 14, 16, 18};
foreach(var permittedMonth in PermittedMonths)
{
MyDropDownList.Items.Add(permittedMonth.ToString(), permittedMonth + " months");
}
public enum SomeEnum
{
Test = 0,
Test1 = 1,
Test2,
}
public SomeEnum SomeEnum {get; init;}
public int SomeEnumId => (int) SomeEnum;
<input type="hidden" asp-for="@Model.SomeEntityId" />