9

为代码量道歉,但这样解释更容易。

我有一个自定义属性 CustomUserData 实现如下:

public class CustomUserData : Attribute
{
   public CustomUserData(object aUserData)
   {
      UserData = aUserData;
   }
   public object UserData { get; set; }
}

枚举的扩展方法为:

public static class EnumExtensions
{
    public static TAttribute GetAttribute<TAttribute>(this Enum aValue) where TAttribute : Attribute
    {
        Type type = aValue.GetType();
        string name = Enum.GetName(type, aValue);
        return type.GetField(name)
                   .GetCustomAttributes(false)
                   .OfType<TAttribute>()
                   .SingleOrDefault();
    }

    public static object GetCustomUserData(this Enum aValue)
    {
        CustomUserData userValue = GetAttribute<CustomUserData>(aValue);
        return userValue != null ? userValue.UserData : null;
    }
}

然后我有一个帮助类,它序列化/反序列化一个具有与之关联的自定义数据的枚举,如下所示:

public static class ParameterDisplayModeEnumListHelper
{
    public static List<ParameterDisplayModeEnum> FromDatabase(string aDisplayModeString)
    {
        //Default behaviour
        List<ParameterDisplayModeEnum> result = new List<ParameterDisplayModeEnum>();

        //Split the string list into a list of strings
        List<string> listOfDisplayModes = new List<string>(aDisplayModeString.Split(','));

        //Iterate the enum looking for matches in the list
        foreach (ParameterDisplayModeEnum displayModeEnum in Enum.GetValues(typeof (ParameterDisplayModeEnum)))
        {
            if (listOfDisplayModes.FindIndex(item => item == (string)displayModeEnum.GetCustomUserData()) >= 0)
            {
                result.Add(displayModeEnum);
            }
        }

        return result;
    }

    public static string ToDatabase(List<ParameterDisplayModeEnum> aDisplayModeList)
    {
        string result = string.Empty;

        foreach (ParameterDisplayModeEnum listItem in aDisplayModeList)
        {
            if (result != string.Empty)
                result += ",";
            result += listItem.GetCustomUserData();
        }

        return result;
    }
}

但是,这是特定ParameterDisplayModeEnum的,我有一堆枚举,我需要以这种方式处理序列化/反序列化,所以我希望有一个通用的,例如:

public static class EnumListHelper<TEnum>
{
    public static List<TEnum> FromDatabase(string aDisplayModeString)
    {
        //Default behaviour
        List<TEnum> result = new List<TEnum>();

        //Split the string list into a list of strings
        List<string> listOfDisplayModes = new List<string>(aDisplayModeString.Split(','));

        //Iterate the enum looking for matches in the list
        foreach (TEnum displayModeEnum in Enum.GetValues(typeof (TEnum)))
        {
            if (listOfDisplayModes.FindIndex(item => item == (string)displayModeEnum.GetCustomUserData()) >= 0)
            {
                result.Add(displayModeEnum);
            }
        }

        return result;
    }

    public static string ToDatabase(List<TEnum> aDisplayModeList)
    {
        string result = string.Empty;

        foreach (TEnum listItem in aDisplayModeList)
        {
            if (result != string.Empty)
                result += ",";
            result += listItem.GetCustomUserData();
        }

        return result;
    }
}

但是,这不起作用,因为无法调用 GetCustomUserData()。有什么建议么?我无法更改自定义属性的使用或枚举的使用。我正在寻找一种通用的方法来进行序列化/反序列化,而不必每次都编写具体的列表帮助程序类。

所有建议表示赞赏。

4

2 回答 2

2

理想情况下,您希望将 TEnum 限制为 Enum 但这不起作用,因为您不能将泛型限制为 Enum Microsoft
但请尝试以下操作,它可能会成功...

if (listOfDisplayModes.FindIndex(item => 
  item == (string)(displayModeEnum as Enum).GetCustomUserData()) >= 0)
于 2013-08-08T04:40:37.987 回答
2

试试这个代码:

public static class EnumListHelper
{
    private static void EnsureIsEnum<TEnum>()
    {
        if (!typeof(TEnum).IsEnum)
            throw new InvalidOperationException(string.Format("The {0} type is not an enum.", typeof(TEnum)));
    }

    public static List<TEnum> FromDatabase<TEnum>(string aDisplayModeString)
        where TEnum : struct
    {
        EnsureIsEnum<TEnum>();
        //Default behaviour
        List<TEnum> result = new List<TEnum>();

        //Split the string list into a list of strings
        List<string> listOfDisplayModes = new List<string>(aDisplayModeString.Split(','));

        //Iterate the enum looking for matches in the list
        foreach (Enum displayModeEnum in Enum.GetValues(typeof(TEnum)))
        {
            if (listOfDisplayModes.FindIndex(item => item == (string)displayModeEnum.GetCustomUserData()) >= 0)
            {
                result.Add((TEnum)(object)displayModeEnum);
            }
        }

        return result;
    }

    public static string ToDatabase<TEnum>(List<TEnum> aDisplayModeList)
        where TEnum : struct
    {
        EnsureIsEnum<TEnum>();
        string result = string.Empty;

        foreach (var listItem in aDisplayModeList.OfType<Enum>())
        {
            if (result != string.Empty)
                result += ",";
            result += listItem.GetCustomUserData();
        }

        return result;
    }
}

var fromDatabase = EnumListHelper.FromDatabase<TestEnum>("test");
EnumListHelper.ToDatabase(fromDatabase);

更新 0

需要明确的是,因为我们不能将泛型限制为 Enum,所以我们应该检查类型TEnum是否为枚举,如果不是则抛出异常。当我们使用FromDatabase我们知道的方法TEnum是 enum 时,我们可以编写以下代码将 enum 强制转换为指定的TEnum

result.Add((TEnum)(object)displayModeEnum)

ToDatabase方法中我们也知道TEnum是枚举,我们可以编写这段代码来转换TEnumEnum类型:

aDisplayModeList.OfType<Enum>()
于 2013-08-08T05:05:58.907 回答