2016-09-16 9 views
-1

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

Мой код это делается быстро:

[XmlRoot("monster")] 
public class monster 
{ 
    public List<flag> flags { get; set; } 
} 

public class flag 
{ 
    [XmlAttribute("summonable")] 
    public int summonable { get; set; } 

    [XmlAttribute("attackable")] 
    public int attackable { get; set; } 
} 

public void XML() 
{ monster monster = new monster 
      { 
       flags = new List<flag> 
       { 
        new flag() { summonable = 0 }, 
        new flag() { attackable = 0 } 
       } 
      }; 
} 

Он выходит хорошо, и я использую Список <>:

<monster> 
<flags> 
    <flag summonable="0" attackable="0" /> 
    <flag summonable="0" attackable="0" /> 
</flags> 
</monster> 

Мне нужно так:

<monster> 
<flags> 
    <flag summonable="0"/> 
    <flag attackable="0"/> 
</flags> 
</monster> 

Спасибо всем, кто помог мне ... Извините за мой плохой Английский

+1

Установлен ли фиксированный набор значений флагов (т. Е. Только «вызываемый» и «атакуемый») или может быть любым количеством флагов? – dbc

+0

только вызываемый и атакующий –

+0

Если это так, почему бы вам не сделать их своими собственными элементами? Например, и ? – Thumper

ответ

1

Прежде всего, поскольку ваш набор флагов исправлен, я бы не рекомендовал List<flag> в вашем классе monster. Вместо этого я бы один flag объекта, например, так:

[XmlRoot("monster")] 
public class monster 
{ 
    public flags flags { get; set; } 
} 

public class flags 
{ 
    public int summonable { get; set; } 

    public int attackable { get; set; } 

    // Add more as required. 
} 

Теперь сериализовать это XML по мере необходимости, вы можете ввести public Flag[] Flags свойства, заселить с именами и значениями ваших основных атрибутов. Это, в свою очередь, может иметь массив в [XmlAnyAttribute] атрибут, который вы заселить с именем атрибута и значением, например, так:

[XmlRoot("monster")] 
public class monster 
{ 
    public flags flags { get; set; } 
} 

public class flags 
{ 
    const string SummonableName = "summonable"; // In c# 6.0 use nameof(summonable) 
    const string AttackableName = "attackable"; // See https://msdn.microsoft.com/en-us/library/dn986596.aspx 

    [XmlIgnore] 
    public int summonable { get; set; } 

    [XmlIgnore] 
    public int attackable { get; set; } 

    [Browsable(false), EditorBrowsable(EditorBrowsableState.Never), DebuggerBrowsable(DebuggerBrowsableState.Never)] 
    [XmlElement("flag")] 
    public Flag[] Flags 
    { 
     get 
     { 
      return new[] 
      { 
       new Flag { Name = SummonableName, Value = XmlConvert.ToString(summonable) }, 
       new Flag { Name = AttackableName, Value = XmlConvert.ToString(attackable) }, 
      }; 
     } 
     set 
     { 
      if (value == null) 
       return; 
      foreach (var attr in value) 
      { 
       if (attr.Name == SummonableName) 
        summonable = XmlConvert.ToInt32(attr.Value); 
       else if (attr.Name == AttackableName) 
        attackable = XmlConvert.ToInt32(attr.Value); 
      } 
     } 
    } 
} 

public class Flag 
{ 
    [XmlIgnore] 
    public string Name { get; set; } 

    [XmlIgnore] 
    public string Value { get; set; } 

    [XmlAnyAttribute] 
    public XmlAttribute[] XmlAttributes 
    { 
     get 
     { 
      var attr = new XmlDocument().CreateAttribute(Name.ToString()); 
      attr.Value = Value; 
      return new [] { attr }; 
     } 
     set 
     { 
      if (value == null || value.Length == 0) 
      { 
       Name = null; 
       Value = null; 
      } 
      else if (value.Length == 1) 
      { 
       Name = value[0].Name; 
       Value = value[0].Value; 
      } 
      else 
      { 
       throw new ArgumentException("Too many attributes"); 
      } 
     } 
    } 
} 

Тогда XML будет выглядеть следующим образом:

<monster> 
    <flags> 
    <flag summonable="0" /> 
    <flag attackable="0" /> 
    </flags> 
</monster> 

fiddle образца.

+0

Очень хорошо !! Можно сократить код? –

+0

@GustavoBatista - Я не могу сразу придумать. Если ваш класс 'flag' имел много свойств, он мог бы быть более компактным, чтобы использовать отражение. То, что вы делаете, противоречит дизайну «XmlSerializer», который предназначен для сопоставления XML с элементами и атрибутами с использованием отражения. – dbc

0

Вы смешиваете имена атрибутов со значениями атрибутов. Я считаю, что может помочь вам в этом:

[XmlRoot("monster")] 
public class monster 
{ 
    public List<flag> flags { get; set; } 
} 

public class flag 
{ 
    [XmlAttribute("Name")] 
    public string Name { get; set; } 

    [XmlAttribute("Value")] 
    public string Value { get; set; } 

} 



public void XML() { 
    monster monster = new monster 
    { 
      flags = new List<flag> 
      { 
       new flag() { Name="summonable", Value = 0 }, 
       new flag() { Name="attackable", Value =0 } 
      } 
     }; 
    } 

Какой должна дать то, что вам нужно

<monster> 
<flags> 
    <flag Name="Summonable" Value="0" /> 
    <flag Name="Attackable" Value="0" /> 
</flags> 
</monster> 
+0

Я не хочу, чтобы имя и значение –

+0

Это, к сожалению, я больше не смогу вам помочь.Остальные два ответа здесь неплохие, но будьте осторожны в ремонтопригодности. – Thumper

+0

Thank You Very Much –

1

Я думаю, вы можете делать то, что вам нужно, пометив flag класс с abstract и выводя ее в двух классах в следующим образом:

public abstract class flag 
{ 

} 

public class summonableFlag : flag 
{ 
    [XmlAttribute("summonable")] 
    public int summonable { get; set; } 
} 

public class attackableFlag : flag 
{ 
    [XmlAttribute("attackable")] 
    public int attackable { get; set; } 
} 

Затем вам нужно отметить List<flag> с XmlElementAttribute сериализовать ваши детали как flag:

[XmlRoot("monster")] 
public class monster 
{ 
    [XmlElement(elementName: "flag")] 
    public List<flag> flags { get; set; } 
} 

Наконец, создание вашего monster объекта будет выглядеть следующим образом:

monster monster = new monster 
      { 
       flags = new List<flag> 
       { 
        new summonableFlag() { summonable = 0 }, 
        new attackableFlag() { attackable = 0 } 
       } 
      }; 

После этого я считаю, что вы получите нужный результат. Я не тестировал его, поэтому напишите, если у вас возникнут проблемы с этим решением.

+0

Привет, это сработало, но как я могу взять пространство имен? ​​ –

+0

@GustavoBatista, это является отдельным вопросом и требует от нас знать, как вы генерируете XML. – Thumper

+0

Спасибо Очень много –