1

逆シリアル化アルゴリズムに汎用関数を再帰的に使用しようとすると問題が発生します。XElement から変数の値を読み込んでいます。ただし、それらがプリミティブでない場合は、そのオブジェクトに対して同じ操作を再帰的に実行する必要があります。ただし、そのオブジェクトは、現在処理されているオブジェクトと同じ型ではありません。たとえば、私が持っている場合

 class someObject
 {
      otherObject obj = new otherObject();
 }

 class otherObject
 {
     int someInt = 123;
 }

デシリアライザーは再帰的に他のオブジェクトに入ります。ただし、問題は、ジェネリック メソッドの型を動的に変更する必要があることです (つまり、コンパイル時にどの型になるかわかりません)。アルゴリズムは次のとおりです。

public static T deserialize<T>(XNode element)
    where T : new()
{
    XElement currentNode = (XElement)element;

    FieldInfo[] fields = getFields<T>();

    T returnValue = new T();

    foreach (FieldInfo field in fields)
    {
        if (field.FieldType.IsPrimitive)
        {
            field.SetValue(returnValue, currentNode.Element(field.Name).Value);
        }
        else
        {
            //The issue is on the following line
            field.SetValue(returnValue, deserialize<???>(currentNode.Element(field.Name).Value));
        }
    }
}

型付きリストとオブジェクトを動的に作成する方法に関するドキュメントをたくさん見てきました。ただし、ジェネリック メソッド呼び出しで型を動的に切り替えることを扱うものは見つかりません。

どんな助けでも大歓迎です!明確でない場合はお知らせください...

4

2 に答える 2

1

私は、ジェネリック メソッドが、インスタンスを作成する別の方法を使用する別の非ジェネリック メソッドを呼び出すようにしますnew T()。外側のジェネリック メソッドはメソッドの呼び出し元にとって便利なので、応答をキャストする必要はありません。内部的には、コードはより単純になります。

.NET フレームワークの逆シリアル化メソッドはすべて、少なくともType、ジェネリック型パラメーター ( <T>) の代わりにインスタンスを取るオーバーロードを持っていることに注意してください。これはあなたが発見している理由によるものです - 型をオブジェクトとして持っていて、ジェネリックメソッドを(賢明に)呼び出してその型パラメータを渡すことができない場合があります。

于 2012-10-29T22:04:17.063 に答える
0

これを試してください。ただし、属性 DataContract、DataMember でクラスをマークする必要があります。

   static readonly XmlWriterSettings ws = new XmlWriterSettings()
    {
        OmitXmlDeclaration = true,
        Encoding = System.Text.Encoding.UTF8
    };


    static XElement ToXElement<T>(T obj)
    {
        StringBuilder sb = new StringBuilder();
        Type valorType = obj.GetType();
        using (var writer = XmlDictionaryWriter.Create(sb, ws))
        {
            DataContractSerializer s = new DataContractSerializer(typeof(T));
            s.WriteObject(writer, obj);
            writer.Flush();
            writer.Close();
        }
        return XElement.Parse(sb.ToString());
    }

    static T ToObj<T>(XElement node)
    {
        string xml = node.ToString(SaveOptions.DisableFormatting);      
        T respuesta = default(T);
        DataContractSerializer dcs = new DataContractSerializer(typeof(T));
        using (StringReader strReader = new StringReader(xml))
        {
            using (XmlReader xmlReader = new XmlTextReader(strReader))
            {
                respuesta = (T)dcs.ReadObject(xmlReader, false);
            }
        }
        return respuesta;
    }

テスト:

    [DataContract]
    public class A
    {
        [DataMember]
        public int Prop { get; set; }
    }

        var node = ToXElement(12);
        int obj = ToObj<int>(node);


        var node2 = ToXElement(new A { Prop = 12 });
        A obj2 = ToObj<A>(node2);
于 2012-10-29T22:50:51.187 に答える