我可以使用以下代码将enum
转换为string
。但是,它只存储一个选定的值。在选择TWO值的情况下,当我使用NHibernate存储它时会被截断。
这是我的代码:
MyEnum { One, Two, Three, Four, Five }
private static readonly string[] myEnum =
Enum.GetNames(typeof(MyEnum));
public string MyProperty
{
get {
var value = new MyEnum();
int i = (int)value;
return i >= 0 && i < myEnum.Length ?
myEnum[i] : i.ToString(); }
set {
Record.MyProperty= value ==
null ? null : String.Join(",", value); }
}
Record
只是public virtual string MyProperty { get; set; }
任何人都可以提供我将如何存储的示例,例如以逗号分隔的形式,选择多个enum
(例如,“一,二,五”由用户选择并且所有三个存储在DB)?
更新
我试图在get{}
:
foreach (int i in Enum.GetValues(typeof(MyEnum)))
{
return i >= 0 && i < myEnum.Length ? myEnum[i] : i.ToString();
}
但收到not all code paths return a value
错误。
问题更新:
如果我用两个string
执行此操作:
part.MyProperty = record.MyProperty;
使用@Jamie Ide下面的IEnumerable<MyEnum>
回答无效,因为我无法将string
转换为MyEnum
。
我如何编写最后一部分,以便在下面的答案中从@Jamie Ide获取IEnumerable<MyEnum>
代码?
答案 0 :(得分:3)
正如我的评论中所提到的,除非绝对要求将枚举存储为字符串,否则我建议使用[Flags]
属性设置枚举并创建将枚举存储为int的约定。这是我使用的(注意我正在使用FluentNH):
惯例
public class EnumConvention : IUserTypeConvention
{
public void Accept(IAcceptanceCriteria<IPropertyInspector> criteria)
{
// You can use this if you don't want to support nullable enums
// criteria.Expect(x => x.Property.PropertyType.IsEnum);
criteria.Expect(x => x.Property.PropertyType.IsEnum ||
(x.Property.PropertyType.IsGenericType &&
x.Property.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>) &&
x.Property.PropertyType.GetGenericArguments()[0].IsEnum)
);
}
public void Apply(IPropertyInstance target)
{
target.CustomType(target.Property.PropertyType);
}
}
枚举
请注意,为了保持按位比较的正常运行,您必须小心设置值。
// Note I use long to support enough enum values
[Flags]
public enum MyEnum : long
{
Foo = 1,
Bar = 1 << 1,
Baz = 1 << 2
}
我相信你不应该做任何事情。无需迭代设置或检索,无需任何操作。要测试是否存在值,可以在枚举上使用HasFlag()
扩展方法。
要修改MvcGrabBag代码以支持此类枚举,您需要更改GetItemsFromEnum
方法,如下所示:
public static IEnumerable<SelectListItem> GetItemsFromEnum<T>(T enumeration = default(T)) where T : struct
{
FieldInfo[] fields = enumeration.GetType().GetFields(BindingFlags.Public | BindingFlags.Static);
return from field in fields
let value = Enum.Parse(enumeration.GetType(), field.Name)
let descriptionAttributes = field.GetCustomAttributes(typeof(DescriptionAttribute), true)
select new SelectListItem
{
Text = descriptionAttributes.Length > 0
? ((DescriptionAttribute)descriptionAttributes[0]).Description
: field.Name,
Value = Convert.ToInt64(value).ToString(),
Selected = (Convert.ToInt64(enumeration) & Convert.ToInt64(value)) == Convert.ToInt64(value)
};
}
请注意,我仅将其保留为通用,因为我不知道该工具包的其他方面取决于该签名。但是,您可以看到没有必要删除<T>
并拥有public static IEnumerable<SelectListItem> GetItemsFromEnum(Enum enumeration)
这样的签名,它会正常工作。
另请注意,此代码使用的是支持从Description
属性派生的名称的约定。我用它来让我的标签更具人性化。枚举看起来像这样:
[Flags]
public enum MyEnum : long
{
[Description("Super duper foo")]
Foo = 1,
[Description("Super duper bar")]
Bar = 1 << 1,
// With no description attribute it will use the ToString value
Baz = 1 << 2
}
答案 1 :(得分:1)
这是一个快速而肮脏的解决方案。在此解决方案中,_myEnumString将映射为私有字段并存储在数据库中。正如评论中所提到的,可以使用另一个表将数组存储为集合,如this question的答案所示,或者在this question中的一个表中。
public enum MyEnum { One, Two, Three, Four, Five }
public class MyClass
{
private string _myEnumString;
public IEnumerable<MyEnum> MyEnums
{
get
{
return Array.ConvertAll(_myEnumString.Split(','), s => (MyEnum)Enum.Parse(typeof(MyEnum), s));
}
set
{
_myEnumString = string.Join(",", value.Select(v => v.ToString()));
}
}
}
更新
假设record.MyProperty和part.MyProperty都是MyEnum名称的分隔字符串(例如“One,Two,Three”),那么您可以映射MyProperty并创建一个只读属性以返回MyEnum的集合。
public class MyClass
{
public string MyProperty { get; set; }
public IEnumerable<MyEnum> MyEnums
{
get
{
return Array.ConvertAll(MyProperty.Split(','), s => (MyEnum)Enum.Parse(typeof(MyEnum), s));
}
}
}