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