Using reflection to serialize files

流过昼夜 提交于 2019-12-12 22:30:37

问题


In my company's application, there's a viewer that will take a message and create an XML document out of it so it can be presented nicely for the customers. Each message has their own class and so far must individually be written like in the examle below. The class name is given in the "m_msgTypeVersion", so I figured it should be possible to use reflection to generalize the cases in this switch statement so it doesn't have to be updated when new message types are added to the application.

However, I am having a bit of trouble doing this. I don't know how to cast to the specific type. I am using .NET 3.5, so the dynamic keyword isn't there. But I need to cast the instance to the specific class instead of Object.

And how to use the Serializer? It says it needs a T. But my type doesn't work with this. It gives a syntax error.

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;

My attempt....

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:


Basically, you've got three choices here (in the absence of dynamic); do everything in reflection, do hardcore meta-programming, or use a single reflection hack to jump into a generic method. The latter is probably your best option, so:

Step 1: create a generic method that does what you want:

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

Step 2: call that method for the unknown type via reflection

Type type = Type.GetType("m_msgTypeVersion");
typeof(YourEnclosingType).GetMethod("EvilHack").MakeGenericMethod(type)
            .Invoke(null, args);

Note you can add a return type etc and catch the return value from .Invoke. The leading null in the .Invoke call is the instance - null in this case because it is a static method; replace that with the target instance if you make the method non-static. If you make the method non-public, you'll need to specify BindingFlags in the GetMethod call.

Fully working example:

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);
    }
}


来源:https://stackoverflow.com/questions/27500819/using-reflection-to-serialize-files

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!