我在尝试以递归方式使用泛型函数进行反序列化算法时遇到问题。我通过它们的值加载XElement中的变量。但是,如果它们不是原语,我必须递归地对该对象执行相同的操作。但是,该对象与正在处理的当前对象的类型不同。所以,例如,如果我有
class someObject
{
otherObject obj = new otherObject();
}
class otherObject
{
int someInt = 123;
}
反序列化器递归进入另一个对象。但是,问题是我必须动态更改泛型方法的类型(即,我不知道在编译时它将是什么类型)。算法如下:
public static T deserialize<T>(XNode element)
where T : new()
{
XElement currentNode = (XElement)element;
FieldInfo[] fields = getFields<T>();
T returnValue = new T();
foreach (FieldInfo field in fields)
{
if (field.FieldType.IsPrimitive)
{
field.SetValue(returnValue, currentNode.Element(field.Name).Value);
}
else
{
//The issue is on the following line
field.SetValue(returnValue, deserialize<???>(currentNode.Element(field.Name).Value));
}
}
}
我已经看到很多关于如何动态创建类型化列表和对象的文档。但是,我找不到任何涉及在泛型方法调用上动态切换类型的内容。
非常感谢任何帮助!如果我不清楚,请告诉我......
答案 0 :(得分:1)
我会让泛型方法调用另一个私有非泛型方法,该方法使用不同的方法创建实例而不是new T()
。外部泛型方法对方法的调用者来说很方便,因此他们不必转换响应。在内部,您的代码将更简单。
请注意,.NET框架的反序列化方法至少都有重载,这些重载采用Type
实例而不是泛型类型参数(<T>
)。这是你发现的原因 - 有时你将类型作为对象,然后你不能(理智地)调用泛型方法并传递该类型参数。
答案 1 :(得分:0)
试试这个,但你必须用属性DataContract,DataMember
标记该类 static readonly XmlWriterSettings ws = new XmlWriterSettings()
{
OmitXmlDeclaration = true,
Encoding = System.Text.Encoding.UTF8
};
static XElement ToXElement<T>(T obj)
{
StringBuilder sb = new StringBuilder();
Type valorType = obj.GetType();
using (var writer = XmlDictionaryWriter.Create(sb, ws))
{
DataContractSerializer s = new DataContractSerializer(typeof(T));
s.WriteObject(writer, obj);
writer.Flush();
writer.Close();
}
return XElement.Parse(sb.ToString());
}
static T ToObj<T>(XElement node)
{
string xml = node.ToString(SaveOptions.DisableFormatting);
T respuesta = default(T);
DataContractSerializer dcs = new DataContractSerializer(typeof(T));
using (StringReader strReader = new StringReader(xml))
{
using (XmlReader xmlReader = new XmlTextReader(strReader))
{
respuesta = (T)dcs.ReadObject(xmlReader, false);
}
}
return respuesta;
}
测试:
[DataContract]
public class A
{
[DataMember]
public int Prop { get; set; }
}
var node = ToXElement(12);
int obj = ToObj<int>(node);
var node2 = ToXElement(new A { Prop = 12 });
A obj2 = ToObj<A>(node2);