2013-09-20 4 views
2

Как я могу импортировать элементы xml в объект? Мой код ниже не работает, он не работает в SetValue, и я не могу понять, почему.C# - XDocument/linq to object

Но даже тогда я подозреваю, что linq имеет гораздо более чистый способ сделать это, но я не могу найти примеров.

class Printers { 
    public List<Printer> list = new List<Printer>(); 

    public Printers() 
    { 
     var xDoc = XDocument.Load(Properties.Settings.Default.XmlSetupPath).Root; 
     var xPrinters = xDoc.Element("printers").Elements(); 
     foreach (var xPrinter in xPrinters) 
     { 
      var printer = new Printer(); 
      foreach (var xEl in xPrinter.Elements()) 
      { 
       printer.GetType().GetProperty(xEl.Name.ToString()).SetValue(printer, xEl.Value); 
      } 
     } 

    } 

} 

class Printer 
{ 
    public string name; 
    public string ip; 
    public string model; 
    public string infx86; 
    public string infx64; 
    public string location; 
    public string comment; 
} 

мой XML:

<printers> 
<printer> 
    <name>my Printer</name> 
    <ip>192.168.100.100</ip> 
    <model>Brother</model> 
    <driver>ab</driver> 
    <infx86>ab\cd.INF</infx86> 
    <comment>Copycenter</comment> 
</printer> 
<printer> 
    <name>my Printer</name> 
    <foobar>oh no!</foobar> 
</printer> 
</printers> 

Я хочу

+1

Обратите внимание, что C# уже есть [класс 'XmlSerializer'] (http://msdn.microsoft.com/en-us/library/system.xml.serialization. xmlserializer.aspx). – Brian

+0

Хотя Джон дал правильный ответ на мой вопрос, XmlSerializer - лучшее решение для меня. Простой пример: http://www.jonasjohn.de/snippets/csharp/xmlserializer-example.htm –

ответ

5

Вы просите свойства - но ваш тип имеет только поля. Либо сделать их свойства, как это:

public string name { get; set; } 

... или использовать Type.GetField вместо этого.

С точки зрения, что делает его красивее, я бы лично добавить статический метод FromXElement к вашему Printer класса, в какой момент вы могли бы:

list = xDoc.Element("printers") 
      .Elements() 
      .Select(Printer.FromXElement) 
      .ToList(); 

Или вы могли бы написать универсальный метод для создания нового экземпляр и заполнить его с помощью отражения, например

public static T FromXElement<T>(XElement element) where T : class, new() 
{ 
    T value = new T(); 
    foreach (var subElement in element.Elements()) 
    { 
     var field = typeof(T).GetField(subElement.Name.LocalName); 
     field.SetValue(value, (string) subElement); 
    } 
    return value; 
} 

Тогда:

list = xDoc.Element("printers") 
      .Elements() 
      .Select(XmlReflection.FromXElement<Printer>) 
      .ToList();