1

オブジェクトを xml 逆シリアル化の結果の型に渡し、強い型付けを維持したいと考えています。

したがって、デシリアライゼーション クラスは、この場合は Result と Result2 である IResult インターフェイスを実装する任意の型を取ることができます。

getObject メソッドを動的に返すようにすることでこれを機能させましたが、コンパイル時のチェックを維持したいので、可能だと思います。

以下の例のようにジェネリックを使用してみましたが、deser.getObject(doc()); 行は私に「使用法から推測することはできません」というコンパイルエラーを与えます。

助けてくれてありがとう。

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;

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

            var deser = new Deserialised(new Result());
            var result = deser.getObject(doc());

            var deser2 = new Deserialised(new Result2());
            var result2 = deser.getObject(doc());

            Console.Writeline(result.status);
            Console.Writeline(result2.status);
        }

        public XmlDocument doc()
        {
            var doc = new XmlDocument();
            var el = (XmlElement)doc.AppendChild(doc.CreateElement("Result"));
            el.SetAttribute("status", "ok");
            el.SetAttribute("status2", "not ok");
            return doc;

        }

    }

    class Deserialised
    {

        private IResult result;
        private Type resultType;

        public Deserialised(IResult _result)
        {
            result = _result;
            resultType = Type.GetType(result.GetType().AssemblyQualifiedName);
        }


        public T getObject<T>(XmlDocument xml)
        {
            var mySerializer = new XmlSerializer(resultType);
            var myStream = new MemoryStream();
            xml.Save(myStream);
            myStream.Position = 0;
            var r = mySerializer.Deserialize(myStream);
            return (T)r;
        }

    }

    interface IResult
    {
        public string status {get;set;}
    }



    [Serializable]
    public class Result :IResult
    {
        [XmlAttribute]
        public string status { get; set; }
    }

    [Serializable]
    public class Result2 : IResult
    {
        [XmlAttribute]
        public string status2 { get; set; }
    }
}
4

3 に答える 3

1

実際、それはうまくいきません - コンパイラはそれを知る方法がありませんT。は、実行時のメソッドの結果ではなく、コンパイル時Tの呼び出し元から取得されることに注意してください。リフレクション/ジェネリックを切り替える方法はありますが、見苦しく、ここではあまり役に立ちませ。代わりに戻ります:object

public object GetObject(XmlDocument xml) {
    var mySerializer = new XmlSerializer(resultType);
    using(var myStream = new MemoryStream()) {
        xml.Save(myStream);
        myStream.Position = 0;
        return mySerializer.Deserialize(myStream);
    }
}

そして、呼び出し元にdynamicetcを処理させます:

var deser = new Deserialised(new Result());
dynamic result = deser.GetObject(doc());

var deser2 = new Deserialised(new Result2());
dynamic result2 = deser.GetObject(doc());

Console.Writeline(result.status);
Console.Writeline(result2.status);

dynamic上記の理由により.status、2 つの inConsole.WriteLineは引き続き機能します。

于 2012-10-30T09:47:56.037 に答える
0

私の意見では、あなたが自分で提供した答えは物事を過度に複雑にしています。(他の奇妙なことをすることに加えて、...私のコメントを参照してください。)

ここでジェネリックを使用しても何も得られません。次のアプローチを使用することもできますが、両方の要件が引き続き適用されます。

public IResult GetObject(XmlDocument xml)
{
    var mySerializer = new XmlSerializer(resultType);
    using (var myStream = new MemoryStream())
    {
        xml.Save(myStream);
        myStream.Position = 0;
        return (IResult)mySerializer.Deserialize(myStream);
    }
}

...次のように呼び出すだけです。

var deser = new Deserialised(new Result());
var result = (Result)deser.getObject(doc());

var deser2 = new Deserialised(new Result2());
var result2 = (Result2)deser.getObject(doc());

実装されていないものにキャストするIResultと、コンパイラ エラーが発生します。


ここで何をしようとしているのかは明確ではありませんが、Deserialisedジェネリックを作成したとします。

class Deserialised<T>
    where T : IResult
{

    private T result;
    private Type resultType;

    public Deserialised(T _result)
    {
        result = _result;
    }


    public T getObject(XmlDocument xml)
    {
        var mySerializer = new XmlSerializer(typeof(T));
        var myStream = new MemoryStream();
        xml.Save(myStream);
        myStream.Position = 0;
        var r = (T)mySerializer.Deserialize(myStream);
        return r;
    }

}

_resultパラメータとして渡して保存するのはなぜですか?あなたが知らなかったので、あなたはそれを必要としただけだと思いますtypeof()か?その場合は、ドロップするだけです。再びそうすると、必要なキャストを定義するという唯一の目的で、ジェネリックパラメーターを定義するクラスになります。

于 2012-11-06T12:31:32.880 に答える
-1

だから私は私の2つの要件の解決策を見つけました.1.型で渡されたものはIResultインターフェースを実装しています.2.返されたオブジェクトは静的に型付けされています. 以下のような制約を持つ一般的なメソッド

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;

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

            var result = new Deserialised().getObject<Result>();

            var result2 = new Deserialised().getObject<Result2>();

            Console.WriteLine(result.status);
            Console.WriteLine(result.errorMessage);
            Console.ReadLine();


        }
    }

    class Deserialised
    {

        public T getObject<T>() where T : IResult
        {
            try
            {
                var instance = Activator.CreateInstance<T>();
                var mySerializer = new XmlSerializer(instance.GetType());
                var myStream = new MemoryStream();
                doc().Save(myStream);
                myStream.Position = 0;
                var r = mySerializer.Deserialize(myStream);
                throw new DivideByZeroException();
                return (T)r;
            }

            catch (Exception exp)
            {
                var instance = Activator.CreateInstance<T>();
                instance.errorMessage = "something wrong here";
                return instance;
            }
            ;
        }

    public static XmlDocument doc()
        {
            var doc = new XmlDocument();
            var el = (XmlElement)doc.AppendChild(doc.CreateElement("Result"));
            el.SetAttribute("status", "ok");
            el.SetAttribute("status2", "notok");
            return doc;

        }

    }

    interface IResult
    {
        string status { get; set; }
        string errorMessage { get; set; }
    }

    [Serializable]
    public class Result : IResult
    {
        [XmlAttribute]
        public string status { get; set; }

        [XmlAttribute]
        public string errorMessage { get; set; }

        [XmlAttribute]
        public string message { get; set; }
    }

    [Serializable]
    public class Result2 : IResult
    {
        [XmlAttribute]
        public string status { get; set; }

        [XmlAttribute]
        public string message2 { get; set; }

        [XmlAttribute]
        public string errorMessage { get; set; }
    }

    [Serializable]
    public class Result3
    {
        [XmlAttribute]
        public string status { get; set; }

        [XmlAttribute]
        public string message2 { get; set; }

        [XmlAttribute]
        public string errorMessage { get; set; }
    }
}
于 2012-11-06T12:11:58.833 に答える