如何解决"两者都使用XML类型名称X,使用XML属性为类型指定唯一的XML名称和/或名称空间"?

ViR*_*iTy 11 c# serialization attributes

我有以下枚举定义......

namespace ItemTable
{
  public enum DisplayMode
  {
    Tiles,
    Default
  }
}

namespace EffectiveItemPermissionTable
{
  public enum DisplayMode
  {
    Tree,
    FullPaths
  }
}
Run Code Online (Sandbox Code Playgroud)

......然后我有以下课程......

public class Table<TDisplayMode>
  where TDisplayMode: struct
{
  // public
    public TDisplayMode DisplayMode
    { 
      get { return mDisplayMode; }
      set { mDisplayMode = value; }
    }

  // private
    private TDisplayMode mDisplayMode;
}

public class ItemTable : Table<ItemTable.DisplayMode>
{}

public class EffectiveItemPermissionTable : Table<EffectiveItemPermissionTable.DisplayMode>
{}

public class UISettings
{
  public UISettings()
  {
    ItemTable = new ItemTable();
    EffectiveItemPermissionTable = new EffectiveItemPermissionTable();
  }

  public ItemTable ItemTable { get; set; }
  public EffectiveItemPermissionTable EffectiveItemPermissionTable { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

...当我尝试用...序列化UISettings的实例时...

System.Xml.Serialization.XmlSerializer lSerializer =
  new System.Xml.Serialization.XmlSerializer(typeof(UISettings));
Run Code Online (Sandbox Code Playgroud)

...我收到以下错误:

Types 'UISettings.Table`1[EffectiveItemPermissionTable.DisplayMode]' and
'UISettings.Table`1[ItemTable.DisplayMode]' both use the XML type name,
'TableOfDisplayMode', from namespace ''.

Use XML attributes to specify a unique XML name and/or namespace for the type.
Run Code Online (Sandbox Code Playgroud)

我曾尝试使用XmlType attribubtes和网上发布的各种解决方案,但没有任何效果.XML类型名称始终TableOfDisplayMode如错误中所述.

现在唯一的解决方案是重命名其中一个枚举,例如,DisplayMode_但我觉得相当难看.

ren*_*ene 8

您需要使用类的属性上的属性来提供命名空间:XmlElementUISettings

public class UISettings
{
    public UISettings()
    {

        ItemTable = new ItemTable();
        EffectiveItemPermissionTable = new EffectiveItemPermissionTable();
    }
    [XmlElement(Namespace = "Item")]
    public ItemTable ItemTable { get; set; }
    [XmlElement(Namespace = "Permissions")]
    public EffectiveItemPermissionTable EffectiveItemPermissionTable { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

在这里应用时,这将是您的序列化输出:

<?xml version="1.0" encoding="utf-16"?>
<UISettings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">  
   <ItemTable xmlns="Item">    
      <DisplayMode>Tiles</DisplayMode>  
   </ItemTable>  
   <EffectiveItemPermissionTable xmlns="Permissions">    
       <DisplayMode>FullPaths</DisplayMode>  
   </EffectiveItemPermissionTable>
</UISettings>
Run Code Online (Sandbox Code Playgroud)

或者,也许更干净,您可以在类型上提供命名空间:

[XmlType(Namespace="Item")]
public class ItemTable : Table<ItemTableNS.DisplayMode>
{ }

[XmlType(Namespace = "Permission")]
public class EffectiveItemPermissionTable : Table<EffectiveItemPermissionTableNS.DisplayMode>
{ }
Run Code Online (Sandbox Code Playgroud)

这将序列化为:

<?xml version="1.0" encoding="utf-16"?>
<UISettings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <ItemTable>
    <DisplayMode xmlns="Item">Tiles</DisplayMode>
  </ItemTable>
  <EffectiveItemPermissionTable>
    <DisplayMode xmlns="Permission">FullPaths</DisplayMode>
  </EffectiveItemPermissionTable>
</UISettings>
Run Code Online (Sandbox Code Playgroud)


Ale*_*lex 5

我意识到这个答案对于OP来说可能为时已晚,但是有一种方法可以不使用名称空间,因此我将在这里留下一个答案,以防有人追随我并需要解决方案。

该问题是由以下事实引起的:XmlSerializer命名类型的方式X<Y>是通过给它命名XOfY。因此,当您有两个都源自的类型时Table<TDisplayMode>,您会得到该错误,因为TableOfDisplayMode尽管实际上使用了不同的枚举,但它们在内部都被称为。

这是因为ItemTableEffectiveItemPermissionTable实际上不是从同一类型继承!一个从继承,Table<ItemTable.DisplayMode>另一个从继承Table<EffectiveItemPermissionTable.DisplayMode>。这不仅仅限于继承。如果您还尝试在同一XML对象图中直接使用它们,则会遇到相同的问题。

现在,对于该问题的非泛型对应物,您只需[XmlType]对这两种类型打点,然后将其命名为“ day”。但是您不能在这里这样做。虽然Table<ItemTable.DisplayMode>Table<EffectiveItemPermissionTable.DisplayMode>是不同的类型,但是它们共享相同的类定义,因此通过尝试使用[XmlType],可以为它们指定不同的名称,但仍使用相同的名称。

所以,你可以做什么?XmlAttributeOverrides营救!它使您可以覆盖XmlSerializer给出给封闭的泛型类型的名称,这意味着您最终可以为Table<ItemTable.DisplayMode>和赋予不同的名称Table<EffectiveItemPermissionTable.DisplayMode>

var xmlOverrides = new XmlAttributeOverrides();

var xmlAttribs = new XmlAttributes();   
xmlAttribs.XmlType = new XmlTypeAttribute("TableOfItemTableDisplayMode");
xmlOverrides.Add(typeof(Table<ItemTable.DisplayMode>), xmlAttribs);

xmlAttribs = new XmlAttributes();
xmlAttribs.XmlType = new XmlTypeAttribute("TableOfEffectiveItemPermissionTableDisplayMode");
xmlOverrides.Add(typeof(Table<EffectiveItemPermissionTable.DisplayMode>), xmlAttribs);

System.Xml.Serialization.XmlSerializer lSerializer =
    new System.Xml.Serialization.XmlSerializer(typeof(UISettings), xmlOverrides);
Run Code Online (Sandbox Code Playgroud)

和瞧!现在假设您还[XmlType]DisplayMode枚举使用了不同的名称,以使它们的名称也不会冲突,那么您自己就可以正常工作了!