1

我想将一个对象传递给 xml 反序列化的结果类型并保持强类型。

所以反序列化类可以采用任何实现 IResult 接口的类型,在这种情况下是 Result 和 Result2。

我通过使 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);
    }
}

然后让调用者处理dynamic等:

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中的Console.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;
    }

}

Why are you even passing _result as a parameter and storing it? My guess is you only needed it since you didn't know about typeof()? In that case simply drop it. After doing so again you just end up with a class which defines your generic parameter, with again the sole purpose to define the required cast.

于 2012-11-06T12:31:32.880 回答
-1

所以我找到了一个解决方案,我的两个要求 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 回答