2012-04-29 25 views
1

當我將一個「XmlAttribute/XmlElement」添加到一個接口的屬性中,並且其他100個類從這個接口繼承時,將該對象序列化爲XML時 - 爲什麼我輸入的屬性名稱沒有在序列化後顯示在XML文件中?Interface中的XmlAttribute/XmlElement(序列化時元素名稱未更改) - 爲什麼?

interface Test 
{ 
    [XmlAttribute("Name")] 
    bool PropertyName { get; set; } 
} 

保存文件時,顯示「PropertyName」而不顯示「Name」。

有沒有什麼辦法讓它工作,所以有XMLATTRIBUTES一個廣告載體添加到界面的值變化無處不在,而不是價值,因爲如果幾班從相同的接口繼承它需要大量的時間補充所有這些屬性到所有繼承它的類,並且更改屬性的名稱將更容易,而不是更改其中的100個。

+0

請不要用「C#」和這樣的前綴您的圖書。這就是標籤的用途。 –

回答

1

Deukalin,花了一些時間,使它與類和接口的綜合樹一起工作。

這裏是工作的代碼

public interface ITestX 
    { 
     [XmlAttribute("NameX")] 
     string PropertyNameX { get; set; } 
    } 

    public interface ITestY 
    { 
     [XmlAttribute("NameY")] 
     string PropertyNameY { get; set; } 
    } 

    public interface ITestZ 
    { 
     [XmlAttribute("NameZ")] 
     string PropertyNameZ { get; set; } 
    } 

    public abstract class TestC : ITestZ 
    { 
     public abstract string PropertyNameZ { get; set; } 
    } 

    public abstract class TestA : TestC, ITestX, ITestY 
    { 
     public abstract string PropertyNameX { get; set; } 
     public abstract string PropertyNameY { get; set; } 
    } 

    public class TestB : TestA 
    { 
     public override string PropertyNameX { get; set; } 
     public override string PropertyNameY { get; set; } 
     public override string PropertyNameZ { get; set; } 
    } 

    public static class ClassHandler 
    { 
     public static T GetCustomAttribute<T>(this PropertyInfo propertyInfo, bool inherit) where T : Attribute 
     { 
      object[] attributes = propertyInfo.GetCustomAttributes(typeof(T), inherit); 

      return attributes == null || attributes.Length == 0 ? null : attributes[0] as T; 
     } 

     public static void GetXmlAttributeOverrides(XmlAttributeOverrides overrides, Type type) 
     { 
      if (type.BaseType != null) 
      { 
       GetXmlAttributeOverrides(overrides, type.BaseType); 
      } 

      foreach (Type derived in type.GetInterfaces()) 
      { 
       foreach (PropertyInfo propertyInfo in derived.GetProperties()) 
       { 
        XmlAttributeAttribute xmlAttributeAttribute = ClassHandler.GetCustomAttribute<XmlAttributeAttribute>(propertyInfo, true) as XmlAttributeAttribute; 

        if (xmlAttributeAttribute == null) 
         continue; 

        XmlAttributes attr1 = new XmlAttributes(); 
        attr1.XmlAttribute = new XmlAttributeAttribute(); 
        attr1.XmlAttribute.AttributeName = xmlAttributeAttribute.AttributeName; 
        overrides.Add(type, propertyInfo.Name, attr1); 
       } 
      } 
     } 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      XmlAttributeOverrides XmlAttributeOverrides = new XmlAttributeOverrides(); 
      ClassHandler.GetXmlAttributeOverrides(XmlAttributeOverrides, typeof(TestB)); 
      try 
      { 
       TestB xtest = new TestB() { PropertyNameX = "RajX", PropertyNameY = "RajY", PropertyNameZ = "RajZ" }; 

       StringBuilder xmlString = new StringBuilder(); 
       using (XmlWriter xtw = XmlTextWriter.Create(xmlString)) 
       { 
        XmlSerializer serializer = new XmlSerializer(typeof(TestB), XmlAttributeOverrides); 
        serializer.Serialize(xtw, xtest); 

        xtw.Flush(); 
       } 

       Console.WriteLine(xmlString.ToString()); 
      } 
      catch (Exception ex) 
      { 
       Console.WriteLine(ex.ToString()); 
      } 
} 

下面是樣本的輸出上面

<?xml version="1.0" encoding="utf-16"?><TestB xmlns:xsi="http://www.w3.org/2001/ 
XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" NameZ="RajZ" Na 
meX="RajX" NameY="RajY" /> 
Press any key to continue . . . 
+0

GetXmlAttributeOverrides應該不再返回一個值嗎? – Deukalion

+0

我將添加我的課程的佈局。 – Deukalion

+0

當我從屬性接口實現屬性時,我添加「公共布爾重寫PropertyName {得到{返回_propertyName;}集{{屬性名=值;}}」這給了我錯誤「找不到合適的方法發現覆蓋」,可以成爲它不接受XmlAttribute接口值的原因? – Deukalion

0

某些原因,它不能在.NET中工作......但我想出瞭解決方案,以解決您使用的問題XmlAttributeOverrides。有關它的更多信息,請訪問以下鏈接

http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlattributeoverrides.aspx

您可以通過重構/緩存在您的應用程序優化它這個GetXmlAttributeOverrides()方法的地方。希望能幫助到你。

public interface ITest 
{ 
    [XmlAttribute("Name")] 
    string PropertyName { get; set; } 
} 

public class XTest : ITest 
{ 
    public string PropertyName 
    { 
     get; 
     set; 
    } 
} 

public class Program 
{ 
    static void Main(string[] args) 
    { 

     try 
     { 
      XTest xtest = new XTest() { PropertyName = "Raj" }; 

      StringBuilder xmlString = new StringBuilder(); 
      using (XmlWriter xtw = XmlTextWriter.Create(xmlString)) 
      { 
       XmlSerializer serializer = new XmlSerializer(typeof(XTest), GetXmlAttributeOverrides(typeof(XTest))); 
       serializer.Serialize(xtw, xtest); 

       xtw.Flush(); 
      } 

      Console.WriteLine(xmlString.ToString()); 
     } 
     catch (Exception ex) 
     { 
      Console.WriteLine(ex.ToString()); 
     } 
    } 

    public static XmlAttributeOverrides GetXmlAttributeOverrides(Type derivedType) 
    { 
     Type type = typeof(ITest); 
     XmlAttributeOverrides overrides = new XmlAttributeOverrides(); 

     XmlAttributes attr = new XmlAttributes(); 

     foreach (PropertyInfo propertyInfo in type.GetProperties()) 
     { 
      XmlAttributeAttribute xmlAttributeAttribute = propertyInfo.GetCustomAttribute(typeof(XmlAttributeAttribute), true) as XmlAttributeAttribute; 

      if (xmlAttributeAttribute == null) continue; 

      XmlAttributes attr1 = new XmlAttributes(); 
      attr1.XmlAttribute = new XmlAttributeAttribute(); 
      attr1.XmlAttribute.AttributeName = xmlAttributeAttribute.AttributeName; 
      overrides.Add(derivedType, propertyInfo.Name, attr1); 
     } 

     return overrides; 
    } 
} 

編輯:包含此擴展類應用程序中的

public static class PropertyInfoEx 
{ 
     public static T GetCustomAttribute<T>(this PropertyInfo propertyInfo, bool inherit) where T : Attribute 
     { 
      object[] attributes = propertyInfo.GetCustomAttributes(typeof(T), inherit); 

      return attributes == null || attributes.Length == 0 ? null : attributes[0] as T; 
     } 

} 
+0

如果我要使用你的方法,我不必每次創建一個XmlAttributeOverride時指定它實現的是哪個interace?因此,使其與以前完全一樣。所有的對象實現一個接口,從那裏不同類型的類實現其他接口;所以它不僅僅是一個需要被覆蓋的東西,每次我想序列化XML時,我都必須明確指定哪些接口。另外,我的程序基於找到實現第一個接口的類,並且我在動態程序中使用它們。如果我添加一個新類,程序會自動添加它。 – Deukalion

+0

我只是給了跳起來的方向,使其工作。箱子裏沒有任何東西。您可能需要擴展它以滿足您的需求。 – RajN

+0

此外,發生這種情況:System.Reflection.PropertyInfo'不包含'GetCustomAttribute'的定義,並且沒有找到接受'System.Reflection.PropertyInfo'類型的第一個參數的擴展方法'GetCustomAttribute'(你是否缺少一個using指令或程序集引用?) – Deukalion

1

我改變了代碼,以滿足我的項目更多。我所做的是這樣的:

public static XmlAttributeOverrides GetXmlAttributeOverrides(Type type) 
    { 
     XmlAttributeOverrides overrides = new XmlAttributeOverrides(); 

     foreach (Type derived in ClassHandler.GetImplementedInterfaces(type)) 
     { 

      foreach (PropertyInfo propertyInfo in derived.GetProperties()) 
      { 
       XmlAttributeAttribute xmlAttributeAttribute = ClassHandler.GetCustomAttribute<XmlAttributeAttribute>(propertyInfo, true) as XmlAttributeAttribute; 

       if (xmlAttributeAttribute == null) continue; 

       XmlAttributes attr1 = new XmlAttributes(); 
       attr1.XmlAttribute = new XmlAttributeAttribute(); 
       attr1.XmlAttribute.AttributeName = xmlAttributeAttribute.AttributeName; 
       overrides.Add(type, propertyInfo.Name, attr1); 
      } 
     } 

     return overrides; 
    } 

上實現與性能的inteface都有「我正在努力的目標[XmlAttributeAttribute(SomeName)在他們

不過,當我序列它給人的。同樣的結果,我不從接口獲得屬性值

這是我如何序列化:

public static void SerializeFile(String filename, object obj, bool deleteIfExists = true) 
    { 

     if (deleteIfExists) 
     { 
      FileManager.DeleteFile(filename); 
     } 

     Type[] extraTypes = ClassHandler.GetPropertiesTypes(obj, true); 

     using (var stream = new FileStream(filename, FileMode.Create)) 
     { 
      //XmlSerializer xmlSerialize = new XmlSerializer(obj.GetType(), extraTypes); 
      XmlSerializer xmlSerialize = new XmlSerializer(obj.GetType(), GetXmlAttributeOverrides(obj.GetType()), extraTypes, null, null); 
      xmlSerialize.Serialize(stream, obj); 
     } 
    } 

兩種方法,我從我的ClassHandler類使用:

public static T GetCustomAttribute<T>(this PropertyInfo propertyInfo, bool inherit) where T : Attribute 
    { 
     object[] attributes = propertyInfo.GetCustomAttributes(typeof(T), inherit); 

     return attributes == null || attributes.Length == 0 ? null : attributes[0] as T; 
    } 

    public static List<Type> GetImplementedInterfaces(Type type) 
    { 
     Type[] types = type.GetInterfaces(); 
     List<Type> lTypes = new List<Type>(); 

     foreach(Type t in types) 
     { 
      lTypes.Add(t); 
     } 

     return lTypes; 
    } 

類具有以下結構:

interface IAnimal 
{ 
    // Properties 
    // Methods 
} 

public abstract class Animal : IAnimal 
{ 
    // Implements IAnimal properties and methods 
    // This XmlElement gets written correctly when XML Serializing 
    // Example: 
    [XmlElement("AnimalAge")] 
    public double Age 
    { 
     get { return _age; } 
     set { _age = value; } 
    } 
} 

public abstract class Bird : Animal, IAttributeWings 
{ 
    // Implements Attributes common for all "Birds" 
    // Setting "override" here gives me error 
    public bool HasWings { get { return _hasWings; } set { _hasWings = value; } } 
} 

public class Pelican : Bird, IAttributeCanFly 
{ 
    // Implements Attributes common for all "Pelicans" 
    // Does not implement previous attribute IAttributeWings since Bird class does this 
    // Setting "override" here gives me error as well 
    public bool CanFly { get { return _canFly; } set { _canFly = value; } } 
} 

,然後將屬性接口只具有如「布爾CanFly,布爾hasWings」和這種和其他屬性對特定類別像在本實施例中的特性。

0

在您的代碼中發現了一些問題。以下是更正後的代碼

public static XmlAttributeOverrides GetXmlAttributeOverrides(Type type) 
{ 
    XmlAttributeOverrides overrides = new XmlAttributeOverrides(); 

    // Get all interfaces that the "type" implements (is it same as "derivedType" from previously)? 
    foreach (Type derived in ClassHandler.GetImplementedInterfaces(type)) 
    { 

     foreach (PropertyInfo propertyInfo in derived.GetProperties()) 
     { 
      XmlAttributeAttribute xmlAttributeAttribute = ClassHandler.GetCustomAttribute<XmlAttributeAttribute>(propertyInfo, true) as XmlAttributeAttribute; 

      if (xmlAttributeAttribute == null) continue; 

      XmlAttributes attr1 = new XmlAttributes(); 
      attr1.XmlAttribute = new XmlAttributeAttribute(); 
      attr1.XmlAttribute.AttributeName = xmlAttributeAttribute.AttributeName; 
      overrides.Add(type, propertyInfo.Name, attr1); 
     } 
    } 

    return overrides; 
} 

請親自嘗試。讓我知道它是否有效。

+0

仍然一樣。我將編輯我之前的帖子(使用我的代碼版本)並添加獲取它實現的接口的類。我從中得到結果,所以它不應該是一個問題。 – Deukalion

+0

A類=實現接口的抽象類,類B =繼承類A,類A(子類)的類,類C =類中的對象,其中對象是從中創建的。 C類然後實現它從中獲取屬性的唯一屬性接口。 – Deukalion

+0

請發佈上面描述它的示例類層次結構。 – RajN

相關問題