C# 将泛型与xml反序列化结合使用

C# 将泛型与xml反序列化结合使用,c#,generics,xml-serialization,C#,Generics,Xml Serialization,我希望将对象传递到xml反序列化的结果类型中,并保持强类型 因此,反序列化类可以采用实现IResult接口的任何类型,在本例中为Result和Result2 通过使getObject方法返回动态,我实现了这一点,但我更愿意保持编译时检查,我认为这应该是可能的 我尝试过使用泛型,如下面的示例所示,但是使用了desr.getObject(doc());行给我一个“无法从用法推断”编译错误 谢谢你的帮助 using System; using System.Collections.Generic; u

我希望将对象传递到xml反序列化的结果类型中,并保持强类型

因此,反序列化类可以采用实现IResult接口的任何类型,在本例中为Result和Result2

通过使getObject方法返回动态,我实现了这一点,但我更愿意保持编译时检查,我认为这应该是可能的

我尝试过使用泛型,如下面的示例所示,但是使用了desr.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; }
    }
}
使用系统;
使用System.Collections.Generic;
使用System.IO;
使用System.Linq;
使用系统文本;
使用System.Xml;
使用System.Xml.Serialization;
名称空间问题
{
班级计划
{
静态void Main(字符串[]参数)
{
var deser=新的反序列化(new Result());
var result=desr.getObject(doc());
var deser2=新的反序列化(new Result2());
var result2=desr.getObject(doc());
控制台写入线(结果状态);
Console.Writeline(结果2.status);
}
公共文档文档()
{
var doc=新的XmlDocument();
var el=(XmlElement)doc.AppendChild(doc.CreateElement(“结果”);
el.SetAttribute(“状态”、“正常”);
el.SetAttribute(“状态2”,“不正常”);
退货单;
}
}
类反序列化
{
私有IResult结果;
私有类型resultType;
公共反序列化(IResult\u结果)
{
结果=_结果;
resultType=Type.GetType(result.GetType().AssemblyQualifiedName);
}
公共T getObject(XmlDocument xml)
{
var mySerializer=新的XmlSerializer(resultType);
var myStream=newmemoryStream();
Save(myStream);
myStream.Position=0;
var r=mySerializer.Deserialize(myStream);
返回(T)r;
}
}
接口IResult
{
公共字符串状态{get;set;}
}
[可序列化]
公共类结果:IResult
{
[XmlAttribute]
公共字符串状态{get;set;}
}
[可序列化]
公共类结果2:IResult
{
[XmlAttribute]
公共字符串status2{get;set;}
}
}

事实上,这是行不通的——编译器无法从中知道
t
。请记住,
T
在编译时来自调用方,而不是在运行时来自方法的结果。有很多方法可以在反射/泛型之间切换,但这很难看,在这里也没有多大帮助。我将只返回
对象

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);
    }
}
然后让调用者处理
动态
等:

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

由于上面的
动态
,two
控制台中的
状态
仍然可以工作。

因此我找到了一个解决方案,满足了我的两个需求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; }
    }
}
使用系统;
使用System.Collections.Generic;
使用System.IO;
使用System.Linq;
使用系统文本;
使用System.Xml;
使用System.Xml.Serialization;
名称空间问题
{
班级计划
{
静态void Main(字符串[]参数)
{
var result=新的反序列化().getObject();
var result2=新的反序列化().getObject();
控制台写入线(结果状态);
Console.WriteLine(result.errorMessage);
Console.ReadLine();
}
}
类反序列化
{
public T getObject(),其中T:IResult
{
尝试
{
var instance=Activator.CreateInstance();
var mySerializer=新的XmlSerializer(instance.GetType());
var myStream=newmemoryStream();
doc().Save(myStream);
myStream.Position=0;
var r=mySerializer.Deserialize(myStream);
抛出新的DivideByZeroException();
返回(T)r;
}
捕获(异常扩展)
{
var instance=Activator.CreateInstance();
instance.erromessage=“此处有问题”;
返回实例;
}
;
}
公共静态XmlDocument doc()
{
var doc=新的XmlDocument();
var el=(XmlElement)doc.AppendChild(doc.CreateElement(“结果”);
el.SetAttribute(“状态”、“正常”);
el.SetAttribute(“状态2”、“notok”);
退货单;
}
}
接口IResult
{
字符串状态{get;set;}
字符串错误消息{get;set;}
}
[可序列化]
公共类结果:IResult
{
[XmlAttribute]
公共字符串状态{get;set;}
[XmlAttribute]
公共字符串错误消息{get;set;}
[XmlAttribute]
公共字符串消息{get;set;}
}
[可序列化]
公共类结果2:IResult
{
[XmlAttribute]
公共字符串状态{get;set;}
[XmlAttribute]
公共字符串message2{get;set;}
[XmlAttribute]
公共字符串错误消息{get;set;}
}
[可序列化]
公开课成绩3
{
[XmlAttribute]
公共字符串状态{get;set;}
[XmlAttribute]
公共字符串message2{get;set;}
[XmlAttribute]
公共字符串错误消息{get;set;}
}
}
在我看来,事情过于复杂了。(除了做一些其他奇怪的事情外,……请看我的评论。)

在这里使用泛型没有什么好处。您也可以使用下面的方法,并且您的两个需求都会受到影响
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());
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;
    }

}