1

我可以使用以下代码将 a 转换enum为 a 。string但是,它只存储一个选定的值。在选择了两个值的情况下,当我使用 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选择多个(例如,用户选择“一、二、五”并且所有三个都存储在数据库中)?

更新:

我正在尝试在以下位置执行此操作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;

使用IEnumerable<MyEnum>@Jamie Ide 下面的答案将不起作用,因为我无法转换stringMyEnum.

我将如何编写最后一部分以IEnumerable<MyEnum>从以下答案中的@Jamie Ide 获取代码才能工作?

4

2 回答 2

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
}
于 2013-01-02T15:33:42.647 回答
1

这是一个快速而肮脏的解决方案。在此解决方案中,_myEnumString 将被映射为私有字段并存储在数据库中。如评论中所述,可以使用另一个表将数组存储为集合,如本问题的答案所示,在本问题的一个表

    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 名称的分隔字符串(例如“一、二、三”),那么您可以映射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));
        }
    }

}
于 2012-12-31T14:35:39.207 回答