1

「XmlAttribute/XmlElement」をインターフェイスのプロパティに追加し、100 個の他のクラスがこのインターフェイスから継承するときに、オブジェクトを XML にシリアル化するときに、入力した属性名がシリアル化後に XML ファイルに表示されないのはなぜですか?

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

ファイルを保存すると、「名前」ではなく「プロパティ名」が表示されます。

それを機能させる方法はありますか? XmlAttributes がインターフェイスに追加されたプロパティは、Value ではなくどこでも Value を変更します。これは、いくつかのクラスが同じインターフェイスから継承する場合、それらすべての属性をすべてのクラスに追加するのに多くの時間がかかるためです。それを継承するものであり、それらの 100 を変更する代わりに、属性の名前を変更する方が簡単です。

4

4 に答える 4

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;
    }

私が試しているオブジェクトは、プロパティを持つインターフェイスをすべて実装しており、それらの上に「[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クラスから使用する2つのメソッド:

    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; } }
}

次に、属性インターフェイスには、「bool CanFly、bool hasWings」などのプロパティと、この例のような特定のカテゴリのその他の属性のみが含まれます。

于 2012-04-30T17:12:04.727 に答える
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 . . .
于 2012-04-30T20:29:46.263 に答える
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;
}

自分で試してみてください。うまくいくかどうか教えてください。

于 2012-04-30T18:18:26.297 に答える
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;
        }

}
于 2012-04-30T01:49:34.520 に答える