在调用泛型方法时动态设置<t> </t>

时间:2012-10-29 21:59:59

标签: c# .net reflection

我在尝试以递归方式使用泛型函数进行反序列化算法时遇到问题。我通过它们的值加载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));
        }
    }
}

我已经看到很多关于如何动态创建类型化列表和对象的文档。但是,我找不到任何涉及在泛型方法调用上动态切换类型的内容。

非常感谢任何帮助!如果我不清楚,请告诉我......

2 个答案:

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