Заполнить объект из XML - PullRequest
2 голосов
/ 29 марта 2019

У меня есть существующий объект, подобный этому:

Account account = new Account
{
    Email = "james@example.com",
    Active = true,
    CreatedDate = new DateTime(2013, 1, 20, 0, 0, 0, DateTimeKind.Utc),
    Roles = new List<string>
    {
        "User",
        "Admin"
    }
};

Для обновления некоторых свойств из строки JSON, например

string json = @"{
  'Active': false,
  'Roles': [
    'Expired'
  ]
}";

, я использую метод newtonsoft:

JsonConvert.PopulateObject(json, account);

Как я могу сделать то же самое из строки XML?

<Account>
    <Active>false</Active>    
</Account>

Спасибо

1 Ответ

0 голосов
/ 29 марта 2019

API XmlSerializer не имеет встроенной функции "слияния", однако: он поддерживает шаблон *Specified - это означает: если у вас есть:

public string Email { get; set; }
[XmlIgnore]
public bool EmailSpecified { get; set; }

затем EmailSpecified a: контролирует, сериализуется ли Email, и b: ему присваивается значение true при десериализации из активного значения. Итак: вы можете сделать что-то вроде:

public class Account
{
    public string Email { get; set; }
    [XmlIgnore]
    public bool EmailSpecified { get; set; }
    public bool Active { get; set; }
    [XmlIgnore]
    public bool ActiveSpecified { get; set; }
    public List<string> Roles { get; set; }
    [XmlIgnore]
    public bool RolesSpecified { get; set; }
    public DateTime CreatedDate { get; set; }
    [XmlIgnore]
    public bool CreatedDateSpecified { get; set; }
}

, а затем объединить вручную:

Account account = new Account
{
    Email = "james@example.com",
    Active = true,
    CreatedDate = new DateTime(2013, 1, 20, 0, 0, 0, DateTimeKind.Utc),
    Roles = new List<string>
    {
        "User",
        "Admin"
    }
};

var xml = @"<Account>
<Active>false</Active>
</Account>";
using (var source = new StringReader(xml))
{
    var serializer = new XmlSerializer(typeof(Account));
    var merge = (Account)serializer.Deserialize(source);

    // this bit could also be done via reflection
    if (merge.ActiveSpecified)
    {
        Console.WriteLine("Merging " + nameof(merge.Active));
        account.Active = merge.Active;
    }
    if (merge.EmailSpecified)
    {
        Console.WriteLine("Merging " + nameof(merge.Email));
        account.Email = merge.Email;
    }
    if (merge.CreatedDateSpecified)
    {
        Console.WriteLine("Merging " + nameof(merge.CreatedDate));
        account.CreatedDate = merge.CreatedDate;
    }
    if (merge.RolesSpecified)
    {
        Console.WriteLine("Merging " + nameof(merge.Roles));
        account.Roles = merge.Roles;
    }
}

...