1

我在尝试以递归方式将通用函数用于反序列化算法时遇到问题。我正在通过它们的值从 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));
        }
    }
}

我看过很多关于如何动态创建类型列表和对象的文档。但是,我找不到任何处理在通用方法调用上动态切换类型的东西。

任何帮助是极大的赞赏!如果我不清楚,请告诉我...

4

2 回答 2

1

我会让泛型方法调用另一个私有非泛型方法,该方法使用不同的方法来创建实例,而不是new T(). 外部泛型方法将方便方法的调用者,因此他们不必强制转换响应。在内部,您的代码会更简单。

请注意,.NET 框架的反序列化方法都至少具有采用Type实例而不是泛型类型参数 ( <T>) 的重载。这是您发现的原因 - 有时您将类型作为对象,然后您不能(明智地)调用泛型方法并传递该类型参数。

于 2012-10-29T22:04:17.063 回答
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);
于 2012-10-29T22:50:51.187 回答