2016-09-16 70 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

固定标志值集合(即只有'summonable'和'attackable')还是可以有任何数量的标志? – dbc

+0

只能召唤和攻击 –

+0

如果是这样的话,为什么不让他们成为你自己的元素?例如,? – Thumper

回答

1

首先,由于您的标志设置是固定的,因此我不会在您的monster课程中推荐List<flag>。相反,我将有一个单一的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

非常感谢你 –

1

我想你可以做你的需要通过标记flagabstract和在推导它的两个班通过以下方式:

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

非常感谢你 –

相关问题