我想将一个对象传递给xml反序列化的结果类型并保持强类型。
因此,反序列化类可以采用任何实现IResult接口的类型,在本例中为Result和Result2。
我通过使getObject方法返回动态来实现这一点,但我宁愿保持编译时间检查,我认为它应该是可能的。
我尝试过使用泛型,如下例所示,但是deser.getObject(doc()); line给了我一个“无法从使用中推断”的编译错误。
感谢您的帮助。
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; }
}
}
答案 0 :(得分: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
仍然可以使用。
答案 1 :(得分:0)
在我看来the answer you provided yourself使事情过于复杂。 (除了做一些其他奇怪的事情,...看看我的评论。)
在这里使用泛型没有任何好处。您也可以使用以下方法,您的两个要求仍然有效。
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()
?在那种情况下,简单地放弃它。再次这样做之后,您最终会得到一个定义您的泛型参数的类,同样唯一的目的是定义所需的强制转换。
答案 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; }
}
}