Как десериализовать два разных файла xmls в два разных объекта класса в C #? - PullRequest
2 голосов
/ 05 января 2012

Предположим, у меня есть два разных xml-файла в качестве встроенного ресурса в одной сборке:

x.xml

<car brand="Hummer">
    <type ... />
    <chasis ... />
</car>

y.xml

<shark species="HammerHead">
    <color ... />
    <maxLen .... />
</shark>

И у меня есть два класса Car.cs и Shark.cs, чтобы помочь десериализовать их.

Каким будет метод десериализации их на два разных и отдельных объекта?

Следующий код может обрабатывать только один тип одновременно. Не так ли?

string[] manifestResourceNames = assembly.GetManifestResourceNames();        
foreach (string mrn in manifestResourceNames)
{
    Stream stream = assembly.GetManifestResourceStream(mrn);
    XmlSerializer serializer = new XmlSerializer(typeof(Car));
    Car car = (Car)serializer.Deserialize(stream);
    .... .... ....
}

И, когда этот код встретит класс Shark, он сгенерирует исключение.

Ответы [ 4 ]

2 голосов
/ 05 января 2012

Чтобы система была надежной в любом случае, вам необходимо указать пространство имен вашего XML (вы всегда должны быть пространством имен XML в любом случае - но я спасу вас напыщенную речь).Поэтому:

<car xmlns="http://schemas.cars.org/car" brand="Hummer">
  <type /> <chassis />
</car>
<shark xmlns="http://schemas.ocenia.org/predator">
  <lazer-beams>1</lazer-beams>
  <awesome>Hell yeah.</awesome>
</shark>

Тогда ваши атрибуты сериализации в C # XML станут такими:

[XmlRoot("Car", Namespace=CarNamespaceUri)]
public class Car
{
   public const string CarNamespaceUri = "http://schemas.cars.org/car";
   // ...
}

После этого вы напишите что-то вроде XmlSerializerManager.Это позволит сохранить внутренний Dictionary<Tuple<string, string>, XmlSerializer> - который можно заполнить с помощью отражения (ищите все типы с примененным XmlRootAttribute и создайте кортеж в соответствии с Namespace, LocalName и создайте экземпляр XmlSerializer для этого типа).Вероятно, это будет статический класс.

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

public static T Deserialize<T>(XElement element)
{
   return (T)Deserialize(element);
}

public static object Deserialize(XElement element)
{
   // Remember to do more elaborate checks etc.
   using(var r = element.CreateReader())
   {
       return _serializers[Tuple.Create(element.Name.NamespaceName, element.Name.LocalName)].Deserialize(r);
   }
}
1 голос
/ 05 января 2012

Посмотрите на класс XmlSerializer .Из MSDN:

Сериализует и десериализует объекты в и из документов XML.XmlSerializer позволяет вам контролировать, как объекты кодируются в XML.

Если ваша структура классов не совсем соответствует заданному ML, то есть нет корреляции между именами свойств и элементами XML,вам придется использовать атрибуты, чтобы обеспечить подходящее отображение .

Что касается вашего кода выше, экземпляр XmlSerializer создается так, что он сериализует / десериализует один тип.Вам нужно создать отдельные экземпляры этого класса, один для автомобиля, другой для акулы.

0 голосов
/ 12 января 2012

Я бы создал абстрактный базовый класс, подобный следующему

 public abstract class Model<T>
 {
    public static T GetFromXml(String path)
    {
        if (!File.Exists(path))
            return null;
        var serializer = new XmlSerializer(typeof(T));
        return (T)serializer.Deserialize(File.OpenRead(path));
    }
 }

public class Car : Model<Car>
{
    public String Brand { get; set; }
    public String Type { get; set; }
    public String Chasis { get; set; }
}

public class Shark : Model<Shark>
{
    public String Species { get; set; }
    public String Color { get; set; }
    public long MaxLength { get; set; }
}

Вы можете легко получить доступ к статическому методу из любого подкласса

Car myCar = Car.GetFromXml("a.xml");
Shark greatWhite = Shark.GetFromXml("b.xml");

Надеюсь, это то, что вы ищете.

Торстен

0 голосов
/ 05 января 2012

ваш код может обрабатывать только один класс.

я использовал эту ссылку , чтобы узнать о XMLserializer.Здесь вы можете найти несколько хороших примеров.в последнем примере этот код появляется:

static List<Movie> DeserializeFromXML()
{
    XmlSerializer deserializer = new XmlSerializer(typeof(List<Movie>));
    TextReader textReader = new StreamReader(@"C:\movie.xml");
    List<Movie> movies;
    movies = (List<Movie>)deserializer.Deserialize(textReader);
    textReader.Close();

    return movies;
}

вы можете перестроить его, чтобы использовать ваши XML-файлы в этом вопросе:

static List<Car> DeserializeCar()
{
    XmlSerializer deserializer = new XmlSerializer(typeof(List<Car>));
    TextReader textReader = new StreamReader("./car.xml");
    List<Car> cars;
    cars= (List<Car>)deserializer.Deserialize(textReader);
    textReader.Close();

    return cars;
}
static List<Car> DeserializeShark()
{
    XmlSerializer deserializer = new XmlSerializer(typeof(List<Shark>));
    TextReader textReader = new StreamReader("./shark.xml");
    List<Shark> shark;
    shark= (List<Shark>)deserializer.Deserialize(textReader);
    textReader.Close();

    return shark;
}

, вызвав эти 2 функции, вы можете получить оба класса

...