如果我有一个标记的枚举,请说出参数
[Flags]
public enum Shipping { Null=0x00, FedX=0x01, UPS=0x02, AirBrn=0x04, USPS=0x08, Any=0xFF}
我希望将此值存储在Xml配置文件中,例如
[XmlAttribute(AttributeName="shipper")]
public Shipping ShippingOption { get; set; }
我知道我必须将组合值与空格分开,例如,如果我希望配置文件将ShippingOption表示为FedX或UPS,那么Xml将如下所示:
<ElementName shipper="FedX UPS" />
或者如果我想要它代表FedX或UPS或USPS那么
<ElementName shipper="FedX UPS USPS" />
但是,如果我希望它只是UPS,我该怎么把它放在属性中?
(假设枚举没有预定义的值(如Shipping.Any
)
这相当于c#value
var ship = Shipping.Any & ^Shipping.UPS;
我知道我可以省略一个我不想要的,就像这样:
<ElementName shipper="FedX USPS AirBrn " />
但是如果Enum中有许多成员变得单调乏味,(并且随着整个列表的扩展需要维护)。是否有一种简短的方法来表示被标记的枚举的否定?
答案 0 :(得分:1)
这是一个应该有效的原始解决方案。首先,编写一个解析自定义枚举语法的方法 - 在我的实现中,~X
表示&#39;而不是X
&#39;:
private T ParseEnum<T>(string str) where T : struct, IConvertible
{
var result = 0;
foreach (var name in str.Split())
{
if (name.StartsWith("~"))
{
result &= ~(int)(Enum.Parse(typeof(T), name.Substring(1), true));
}
else
{
result |= (int)(Enum.Parse(typeof(T), name, true));
}
}
return (T)(object)result;
}
这是一个非常简单格式函数,与原始XML序列化兼容:
private string FormatEnum<T>(T s) where T : struct, IConvertible
{
return s.ToString().Replace(",", "");
}
现在只需在需要使用此位置的地方设置代理属性,并确保使用XmlIgnore
标记原始内容:
[XmlIgnore]
public Shipping ShippingOption { get; set; }
[XmlAttribute(AttributeName = "shipper")]
public string ShippingOptionString
{
get { return FormatEnum<Shipping>ShippingOption); }
set { ShippingOption = ParseEnum<Shipping>(value); }
}
现在它将能够像这样正确地解析XML:
<ElementName shipper="Any ~UPS" />
不同的序列化库存在其他解决方案,但模式基本相同。将XML属性反序列化为字符串,然后使用自定义解析器解析它以获得所需的枚举结果。