使用反射来序列化文件

时间:2014-12-16 08:58:13

标签: c# reflection serializer

在我公司的应用程序中,有一个查看器会接收消息并从中创建XML文档,以便为客户提供良好的显示。每条消息都有自己的类,到目前为止必须单独编写,如下面的例子中所示。类名在" m_msgTypeVersion"中给出,所以我认为应该可以使用反射来概括这个switch语句中的情况,这样当新的消息类型不是必须更新时添加到应用程序中。

但是,我在这方面遇到了一些麻烦。我不知道如何投射到特定类型。我使用的是.NET 3.5,因此动态关键字不在那里。但我需要将实例强制转换为特定的类而不是Object。

如何使用Serializer?它说它需要一个T.但我的类型并不适用于此。它给出了语法错误。

switch (m_msgTypeVersion)
{
    default:
        throw new NotImplementedException("Message type " + m_msgTypeVersion + " conversion to XmlElement not implemented!");
    case "UTILMD_D11AUN51":
        UTILMD_D11AUN51 utilmd51 = new UTILMD_D11AUN51();
        Serializer<UTILMD_D11AUN51> serUtilmd51 = new Serializer<UTILMD_D11AUN51>();
        if (serUtilmd51.Deserialize(m_ediMsg, out utilmd51, out ex))
            xml = new XmlDocument().ReadNode(serUtilmd51.Serialize(utilmd51, "").Root.CreateReader()) as XmlElement;
        break;
    case "UTILMD_D11AUN51a":
        UTILMD_D11AUN51a utilmd51a = new UTILMD_D11AUN51a();
        Serializer<UTILMD_D11AUN51a> serUtilmd51a = new Serializer<UTILMD_D11AUN51a>();
        if (serUtilmd51a.Deserialize(m_ediMsg, out utilmd51a, out ex))
            xml = new XmlDocument().ReadNode(serUtilmd51a.Serialize(utilmd51a, "").Root.CreateReader()) as XmlElement;
        break;
    case ...

}

return xml;

我的尝试......

Type type = Type.GetType("m_msgTypeVersion");
Object myObject = Activator.CreateInstance(type); // need not object, but cast to specific type
Serializer<type> serUtilmd51 = new Serializer<type>(); // does not work with "type"

1 个答案:

答案 0 :(得分:2)

基本上,你在这里有三个选择(没有动态);做一切反思,做硬核元编程,或使用单个反射黑客跳转到泛型方法。后者可能是你最好的选择,所以:

步骤1:创建一个符合您需要的通用方法:

public static void EvilHack<T>(...args...)
{
     T myObject = Activator.CreateInstance<T>();
     Serializer<T> serUtilmd51 = new Serializer<T>();
     // etc
}

第2步:通过反射

为未知类型调用该方法
Type type = Type.GetType("m_msgTypeVersion");
typeof(YourEnclosingType).GetMethod("EvilHack").MakeGenericMethod(type)
            .Invoke(null, args);

请注意,您可以添加返回类型等,并从.Invoke捕获返回值。在这种情况下,null调用中的前导.Invoke是实例 - null,因为它是static方法;如果使方法非静态,则将其替换为目标实例。如果您将方法设为非public,则需要在BindingFlags调用中指定GetMethod

完全正常的例子:

using System;

class YourEnclosingType
{
    static void Main()
    {
        Type type = Type.GetType("m_msgTypeVersion");
        object[] args = null; // no args
        typeof(YourEnclosingType).GetMethod("EvilHack").MakeGenericMethod(type)
                    .Invoke(null, args);
    }
    public static void EvilHack<T>()
    {
        T myObject = Activator.CreateInstance<T>();
        Serializer<T> serUtilmd51 = new Serializer<T>();
        serUtilmd51.DoIt(myObject);
    }
}
class m_msgTypeVersion // worst. name. ever
{ }
class Serializer<T>
{
    public void DoIt(T obj)
    {
        Console.WriteLine("I'm serializing " + obj);
    }
}