2013-01-06 18 views
4

我有一个包含几个标志的XML,其中一些是无符号的32位整数,而另一些是无符号的64位整数。其中一些用逗号分隔的列表书写,而另一些用十六进制格式。从逗号分隔的列表或整数解析枚举标志

见这个例子:

<Color>Blue,Red</Color> 
<Color>0xC</Color> 

因为我不想写来解析每个枚举的方法,我决定用一个通用的方法。但Visual Studio不会让我构建解决方案。这里是我的方法:

public static T ParseFlags<T>(string value) where T : struct 
{ 
    T result = (T)((object)0); 
    string[] array; 
    // Remove white spaces and delimit string if it is comma-separated 
    if (ParseDelimitedString(value, ',', out array)) 
    { 
     for (int i = 0; i < array.Length; i++) 
     { 
      T flag = (T)((object)0); 
      // Check if value is member of enumeration 
      if (Enum.TryParse<T>(array[i], out flag)) 
      { 
       result |= (T)((object)flag); 
      } 
     } 
    } 
    else 
    { 
     switch (Type.GetTypeCode(Enum.GetUnderlyingType(typeof(T)))) 
     { 
      // Remove hex characters and parse node's inner text 
      case TypeCode.UInt32: 
       result = (T)((object)ParseUint(value)); 
       break; 
      case TypeCode.UInt64: 
       result = (T)((object)ParseUlong(value)); 
       break; 
     } 
    } 
    return result; 
} 

该错误消息我得到的是:

错误1个操作 '| =' 不能应用于类型 'T' 和 'T'

的操作数

有没有办法做到这一点?

+0

不应该这样'结果| =(T)((对象)标志);'是这样,而不是'结果=(T) ((object)标志);' – MethodMan

回答

6

你正在做很多工作,可以为你做。例如,如果您的enum声明为FlagsAttribute,则Enum.Parse将为您解析逗号分隔值。

public static T ParseFlags<T>(string value) where T : struct 
{ 
    T result; 
    ulong temp; 
    if (Enum.TryParse(value, out result)) 
    { 
     return result; 
    } 

    string hexNum = value.StartsWith("0x") ? value.Substring(2) : value; 
    if (ulong.TryParse(hexNum, NumberStyles.HexNumber, null, out temp)) 
    { 
     return (T)Enum.ToObject(typeof(T), temp); 
    } 

    throw new ArgumentException("value could not be parsed"); 
} 

我与各种标志枚举类型与shortint,和背衬ulong值测试此。

+0

我不知道它可以处理逗号分隔值,谢谢。这似乎是一个更好的方法。 – richi3f

0

试试这个:

public static T ParseFlags<T>(string value) where T : struct 
{ 
    long result = 0L; 
    string[] array; 
    // Remove white spaces and delimit string if it is comma-separated 
    if (ParseDelimitedString(value, ',', out array)) 
    { 
     for (int i = 0; i < array.Length; i++) 
     { 
      T flag = default(T); 
      // Check if value is member of enumeration 
      if (Enum.TryParse<T>(array[i], out flag)) 
      { 
       result |= (long)flag; 
      } 
     } 
    } 
    else 
    { 
     switch (Type.GetTypeCode(Enum.GetUnderlyingType(typeof(T)))) 
     { 
      // Remove hex characters and parse node's inner text 
      case TypeCode.UInt32: 
       result = ParseUint(value); 
       break; 
      case TypeCode.UInt64: 
       result = ParseUlong(value); 
       break; 
     } 
    } 
    return (T)((object)result); 
} 

希望它能帮助。

+0

该死的,不能在注释中写代码;) – kzu

0

“| =”在这段代码中的用法让我觉得你打算使用Enum作为bitset,而不仅仅是任何旧的Enum。如果这是真的,你应该做一个小小的修改 - 声明本地的“结果”为int并适当地调整转换,你的return语句应该是“return(T)(object)result”。该线路与“|”有关看起来像:“result | =(int)(object)flag;”。也许,有一个更好的答案,但请注意,enums are integers和你的bitset的情况已经被这个解决方案所覆盖,除非有一些情况我错过了或者你没有说明。

1

如果你知道你在什么解析枚举类型:

[Fact] 
    public void when_parsing_options_then_can_combine_flags() 
    { 
     var values = "Singleline | Compiled"; 

     var options = values.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries) 
      .Select(value => (RegexOptions)Enum.Parse(typeof(RegexOptions), value)) 
      .Aggregate(RegexOptions.None, (current, value) => current |= value); 

     Assert.Equal(RegexOptions.Singleline | RegexOptions.Compiled, options); 
    }