Сопоставление XML значений типа перечисление
Мне нужно разобрать XML-файл, который я получаю от сторонних объектов C#.
Некоторые из XML, которые я получаю, имеют значения перечисления, которые я хочу сохранить в типе enum.
Например, у меня есть следующий xsd xml-файл:
<xsd:simpleType name="brandstof">
<xsd:restriction base="xsd:string">
<!-- Benzine -->
<xsd:enumeration value="B" />
<!-- Diesel -->
<xsd:enumeration value="D" />
<!-- LPG/Gas -->
<xsd:enumeration value="L" />
<!-- LPG G3 -->
<xsd:enumeration value="3" />
<!-- Elektrisch -->
<xsd:enumeration value="E" />
<!-- Hybride -->
<xsd:enumeration value="H" />
<!-- Cryogeen -->
<xsd:enumeration value="C" />
<!-- Overig -->
<xsd:enumeration value="O" />
</xsd:restriction>
</xsd:simpleType>
Я хочу сопоставить это с перечислением, и я дошел до этого:
public enum Fuel
{
B,
D,
L,
E,
H,
C,
O
}
Проблема у меня заключается в том, что XML может содержать значение 3, который я не могу показаться, чтобы положить в перечислимый тип. Есть ли какое-либо решение, чтобы поместить это значение в перечисление.
Я также могу получить другие значения с - или / в них и которые я хочу поместить в тип enum.
Предложения Ану приветствуются!
4 ответов:
Вы можете проанализировать значение атрибута xml обратно в тип enum с помощью:
Но я не думаю, что вы далеко продвинетесь со своими "особыми" ценностями.(var value = Enum.Parse(typeof(Fuel), "B");3,a/и т.д.). Почему бы вам не определить свое перечисление какenum Fuel { Benzine, Diesel, // ... Three, ASlash, // ... }И написать статический метод для преобразования строки в элемент перечисления?
Одна вещь, которую вы могли бы рассмотреть для реализации такого метода, состояла бы в добавлении пользовательских атрибутов к элементам перечисления, содержащим их строковое представление - если значение не имеет точного аналогично в перечислении найдите элемент с атрибутом.
Создать такой атрибут несложно:
/// <summary> /// Simple attribute class for storing String Values /// </summary> public class StringValueAttribute : Attribute { public string Value { get; private set; } public StringValueAttribute(string value) { Value = value; } }И затем вы можете использовать их в своем перечислении:
enum Fuel { [StringValue("B")] Benzine, [StringValue("D")] Diesel, // ... [StringValue("3")] Three, [StringValue("/")] Slash, // ... }Эти два метода помогут вам разобрать строку на элемент enum по вашему выбору:
/// <summary> /// Parses the supplied enum and string value to find an associated enum value (case sensitive). /// </summary> public static object Parse(Type type, string stringValue) { return Parse(type, stringValue, false); } /// <summary> /// Parses the supplied enum and string value to find an associated enum value. /// </summary> public static object Parse(Type type, string stringValue, bool ignoreCase) { object output = null; string enumStringValue = null; if (!type.IsEnum) { throw new ArgumentException(String.Format("Supplied type must be an Enum. Type was {0}", type)); } //Look for our string value associated with fields in this enum foreach (FieldInfo fi in type.GetFields()) { //Check for our custom attribute var attrs = fi.GetCustomAttributes(typeof (StringValueAttribute), false) as StringValueAttribute[]; if (attrs != null && attrs.Length > 0) { enumStringValue = attrs[0].Value; } //Check for equality then select actual enum value. if (string.Compare(enumStringValue, stringValue, ignoreCase) == 0) { output = Enum.Parse(type, fi.Name); break; } } return output; }И раз уж я об этом: здесь все наоборот;)
/// <summary> /// Gets a string value for a particular enum value. /// </summary> public static string GetStringValue(Enum value) { string output = null; Type type = value.GetType(); if (StringValues.ContainsKey(value)) { output = ((StringValueAttribute) StringValues[value]).Value; } else { //Look for our 'StringValueAttribute' in the field's custom attributes FieldInfo fi = type.GetField(value.ToString()); var attributes = fi.GetCustomAttributes(typeof(StringValueAttribute), false); if (attributes.Length > 0) { var attribute = (StringValueAttribute) attributes[0]; StringValues.Add(value, attribute); output = attribute.Value; } } return output; }
Украсьте атрибутом
XmlEnum: http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlenumattribute.aspxpublic enum Fuel { [XmlEnum("B")] Benzine, [XmlEnum("D")] Diesel, [XmlEnum("L")] LpgGas, [XmlEnum("3")] LpgG3, [XmlEnum("E")] Elektrisch, [XmlEnum("H")] Hybride, [XmlEnum("C")] Cryogeen, [XmlEnum("O")] Overig }
Почему вы не можете разобрать строку
[XmlAttribute("brandstof")] public string FuelTypeString { get { return fuel.ToString(); } set { fuel = (Fuel)System.Enum.Parse(typeof(Fuel), value); } } [XmlIgnore()] public Fuel FuelType { get { return fuel; } set { fuel = value; } }Таким образом, вы действительно сериализуете его как строку.
Я создал класс, который обрабатывает это:
class EnumCreator { public static Type CreateEnum(List<string> AValues) { // Get the current application domain for the current thread. AppDomain currentDomain = AppDomain.CurrentDomain; // Create a dynamic assembly in the current application domain, // and allow it to be executed and saved to disk. AssemblyName aName = new AssemblyName("TempAssembly"); AssemblyBuilder ab = currentDomain.DefineDynamicAssembly( aName, AssemblyBuilderAccess.RunAndSave); // Define a dynamic module in "TempAssembly" assembly. For a single- // module assembly, the module has the same name as the assembly. ModuleBuilder mb = ab.DefineDynamicModule(aName.Name, aName.Name + ".dll"); // Define a public enumeration with the name "Elevation" and an // underlying type of Integer. EnumBuilder eb = mb.DefineEnum("EnumValues", TypeAttributes.Public, typeof(int)); // Define two members, "High" and "Low". foreach (string v in AValues) { eb.DefineLiteral(v, AValues.IndexOf(v)); } // Create the type and save the assembly. Type finished = eb.CreateType(); return finished; } }Вы должны сначала прочитать xml-файл и поместить значения в список, вы можете сделать это, например, с объектом XElement.
/ / править: Вот так:
XElement xml = XElement.parse("file.xml"); List<string> enumItems = new List<string>(); foreach(XElement row in xml.Element("xsd:simpleType").Element("xsd:restriction").Elements()) { enumItems.Add(row.Attribute("value").Value); } Type Fuel = EnumCreator.CreatEnum(enumItems);
Comments