gpt4 book ai didi

c# - 扩展枚举,矫枉过正?

转载 作者:太空狗 更新时间:2023-10-29 23:57:48 27 4
gpt4 key购买 nike

我有一个对象需要序列化为 EDI 格式。对于这个例子,我们假设它是一辆汽车。汽车可能不是 b/c 选项随时间变化的最佳示例,但对于真实对象,枚举永远不会改变。

我有很多像下面这样的应用了自定义属性的枚举。

public enum RoofStyle
{
[DisplayText("Glass Top")]
[StringValue("GTR")]
Glass,
[DisplayText("Convertible Soft Top")]
[StringValue("CST")]
ConvertibleSoft,
[DisplayText("Hard Top")]
[StringValue("HT ")]
HardTop,
[DisplayText("Targa Top")]
[StringValue("TT ")]
Targa,
}

通过扩展方法访问属性:

public static string GetStringValue(this Enum value)
{
// Get the type
Type type = value.GetType();

// Get fieldinfo for this type
FieldInfo fieldInfo = type.GetField(value.ToString());

// Get the stringvalue attributes
StringValueAttribute[] attribs = fieldInfo.GetCustomAttributes(
typeof(StringValueAttribute), false) as StringValueAttribute[];

// Return the first if there was a match.
return attribs.Length > 0 ? attribs[0].StringValue : null;
}

public static string GetDisplayText(this Enum value)
{
// Get the type
Type type = value.GetType();

// Get fieldinfo for this type
FieldInfo fieldInfo = type.GetField(value.ToString());

// Get the DisplayText attributes
DisplayTextAttribute[] attribs = fieldInfo.GetCustomAttributes(
typeof(DisplayTextAttribute), false) as DisplayTextAttribute[];

// Return the first if there was a match.
return attribs.Length > 0 ? attribs[0].DisplayText : value.ToString();
}

有一个自定义 EDI 序列化程序,它基于 StringValue 属性进行序列化,如下所示:

    StringBuilder sb = new StringBuilder();
sb.Append(car.RoofStyle.GetStringValue());
sb.Append(car.TireSize.GetStringValue());
sb.Append(car.Model.GetStringValue());
...

还有一种方法可以从StringValue中获取Enum值进行反序列化:

   car.RoofStyle = Enums.GetCode<RoofStyle>(EDIString.Substring(4, 3))

定义为:

public static class Enums
{
public static T GetCode<T>(string value)
{
foreach (object o in System.Enum.GetValues(typeof(T)))
{
if (((Enum)o).GetStringValue() == value.ToUpper())
return (T)o;
}
throw new ArgumentException("No code exists for type " + typeof(T).ToString() + " corresponding to value of " + value);
}
}

最后,对于 UI,GetDisplayText() 用于显示用户友好的文本。

你怎么看?矫枉过正?有没有更好的办法?还是 Goldie Locks(恰到好处)?

只是想在将其永久集成到我的个人框架之前获得反馈。谢谢。

最佳答案

您用来序列化的部分没问题。反序列化部分写得很别扭。主要问题是您使用的是 ToUpper()比较容易损坏的字符串(想想全局化)。这种比较应该用 string.Compare 来完成。相反,或者 string.Equals overload这需要 StringComparison .

另一件事是在反序列化过程中一次又一次地执行这些查找会非常慢。如果您正在序列化大量数据,这实际上可能会非常明显。在这种情况下,您需要从 StringValue 构建 map 到枚举本身 - 将其放入静态 Dictionary<string, RoofStyle>并将其用作往返的查找。换句话说:

public static class Enums
{
private static Dictionary<string, RoofStyle> roofStyles =
new Dictionary<string, RoofStyle>()
{
{ "GTR", RoofStyle.Glass },
{ "CST", RoofStyle.ConvertibleSoft },
{ "HT ", RoofStyle.HardTop },
{ "TT ", RoofStyle.TargaTop }
}

public static RoofStyle GetRoofStyle(string code)
{
RoofStyle result;
if (roofStyles.TryGetValue(code, out result))
return result;
throw new ArgumentException(...);
}
}

它不是那么“通用”,但效率更高。如果您不喜欢字符串值的重复,则将代码提取为单独类中的常量。

如果你真的需要它是完全通用的并且适用于任何枚举,你总是可以在第一次完成转换时延迟加载值字典(使用你编写的扩展方法生成它)。这样做非常简单:

static Dictionary<string, T> CreateEnumLookup<T>()
{
return Enum.GetValues(typeof(T)).ToDictionary(o => ((Enum)o).GetStringValue(),
o => (T)o);
}

附言次要细节,但您可能要考虑使用 Attribute.GetCustomAttribute而不是 MemberInfo.GetCustomAttributes如果您只希望有一个属性。当您只需要一项时,没有理由摆弄所有数组。

关于c# - 扩展枚举,矫枉过正?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3015893/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com