通用枚举约束

4

我接手了一个有很多枚举定义的web api,我想将它们转换为一个称为EnumView的视图模型类,以便可以像下面这样进行序列化...

{Id: , Name: 枚举名称}

public class EnumView
{
    public int Id { get; set; }
    public string Name { get; set; }
}

将Generic类限制为枚举类型后,我收到了警告

约束不能是特殊类'System.Enum'

这是我要使用的通用转换器...

public class EnumViewConverter<T> where T : Enum
{
    public static List<EnumView> ConvertToView()
    {
        List<EnumView> enumViews = new List<EnumView>();

        T[] enumValues = (T[])Enum.GetValues(typeof(T));

        foreach (var enumValue in enumValues)
        {
            var enumView = new EnumView
            {
                Id = (int)enumValue,
                Name = Enum.GetName(typeof(T), enumValue)
            };

            enumViews.Add(enumView);
        }
        return enumViews;
    }
}

如果 T 没有被限制为枚举类型,则以下转换无法编译...

Id = (int)enumValue,

由于缺乏通用枚举约束的问题,如何解决这个问题呢?


好的,你定义了一个枚举类型,但是你要如何使用它呢?通过回答这个问题,我们可以找出转换的目的,然后可能想出一个解决方案。 - Hamed
@leppie - 在发布问题之前,我已经阅读了那个问题/答案,但我觉得它并没有真正回答我的问题。 - Will
@Hamed,不太确定你想要什么——EnumView 应该在 API 中进行序列化。这个枚举类型是用于服务器端的代码中的… - Will
@AmitKumarGhosh 是的,如果我使用 where T: struct,类型 T 并不保证是枚举。我想创建一个枚举所有值的列表,并在 API 中返回它,而不仅仅是序列化单个枚举值。 - Will
@leppie,所以在测试了enumView.Id = (int)EnumUtils.Parse<T>(enumView.Name);之后,我仍然遇到了同样的问题... 类型“T”无法用作泛型类型或方法“EnumClassUtils<TClass>.Parse<TEnum>(string)”中的类型参数“TEnum”。从“T”到“System.Enum”没有装箱转换或类型参数转换。 - Will
显示剩余7条评论
3个回答

3
你可以使用:Id = Convert.ToInt32(enumValue)替代强制转换(int)
如果你想在编译时添加一些“约束”以检查类型,你可以设置“where T : struct”,它至少可以防止设置类类型。

谢谢,我以为我已经测试过了,但它没有起作用;不管怎样,我再试一次,你说得对。 - Will

0

最终我使用了...

public static class EnumViewConverter<T> where T : struct
{
    public static List<EnumView> ConvertToView()
    {
        if (!typeof(T).IsEnum) throw new ArgumentException("T must be an enumerated type");

        List<EnumView> enumViews = new List<EnumView>();

        T[] enumValues = (T[])Enum.GetValues(typeof(T));

        foreach (var enumValue in enumValues)
        {
            var enumView = new EnumView
            {
                Id = Convert.ToInt32(enumValue),
                Name = Enum.GetName(typeof(T), enumValue)
            };

            enumViews.Add(enumView);
        }
        return enumViews;
    }
}

被调用者...

var views = EnumViewConverter<FooBarEnum>.ConvertToView();

感谢所有的帮助,我本来以为我之前试过这个方法了 :(


0
扩展我之前的评论,这个答案中描述的技术使用了一个嵌套类,其泛型参数依赖于其父类来模拟泛型Enum约束。你可以在这里使用这种方法:
public abstract class ConverterClassUtils<TClass> 
    where TClass : class
{
    public class ViewConverter<TInner> where TInner : struct, TClass
    {
        public static List<EnumView> ConvertToView()
        {
            List<EnumView> enumViews = new List<EnumView>();

            TInner[] enumValues = (TInner[])Enum.GetValues(typeof(TInner));

            foreach (var enumValue in enumValues)
            {
                var enumView = new EnumView
                {
                    Id = (int)(object)enumValue,
                    Name = Enum.GetName(typeof(TInner), enumValue)
                };

                enumViews.Add(enumView);
            }
            return enumViews;
        }
    }
}

public class EnumConverter : ConverterClassUtils<Enum> { }

那么以下代码将会编译:

var view = EnumConverter.ViewConverter<SomeEnum>.ConvertToView();

虽然这个不行:

var view = EnumConverter.ViewConverter<int>.ConvertToView();

谢谢你对建议的详细解释。最终,我选择了以下代码,因为它更简单。感谢你的帮助。 - Will

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接