C# 使用反射序列化文件

C# 使用反射序列化文件,c#,reflection,serialization,C#,Reflection,Serialization,在我公司的应用程序中,有一个查看器,它将接收一条消息并从中创建一个XML文档,这样就可以很好地向客户展示它。每个消息都有自己的类,到目前为止必须像下面的示例中那样单独编写。类名在“m_msgTypeVersion”中给出,因此我认为应该可以使用反射来概括这个switch语句中的情况,这样在向应用程序添加新消息类型时就不必更新它 然而,我做这件事有点困难。我不知道如何转换到特定类型。我使用的是.NET3.5,所以这里没有动态关键字。但是我需要将实例强制转换为特定的类,而不是对象 以及如何使用序列化

在我公司的应用程序中,有一个查看器,它将接收一条消息并从中创建一个XML文档,这样就可以很好地向客户展示它。每个消息都有自己的类,到目前为止必须像下面的示例中那样单独编写。类名在“m_msgTypeVersion”中给出,因此我认为应该可以使用反射来概括这个switch语句中的情况,这样在向应用程序添加新消息类型时就不必更新它


然而,我做这件事有点困难。我不知道如何转换到特定类型。我使用的是.NET3.5,所以这里没有动态关键字。但是我需要将实例强制转换为特定的类,而不是对象

以及如何使用序列化程序?它说它需要一个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 ...
开关(m_MSGType版本)
{
违约:
抛出新的NotImplementedException(“消息类型”+m_msgTypeVersion+“转换为未实现的XmlElement!”);
“UTILMD_D11AUN51”案:
UTILMD_D11AUN51 utilmd51=新UTILMD_D11AUN51();
Serializer serUtilmd51=新序列化程序();
if(serUtilmd51.反序列化(m_ediMsg,out utilmd51,out ex))
xml=new XmlDocument().ReadNode(serUtilmd51.Serialize(utilmd51,“”).Root.CreateReader())作为XmlElement;
打破
“UTILMD_D11AUN51a”案:
UTILMD_D11AUN51a utilmd51a=新UTILMD_D11AUN51a();
序列化程序serUtilmd51a=新序列化程序();
if(serUtilmd51a.反序列化(m_ediMsg,out utilmd51a,out ex))
xml=new XmlDocument().ReadNode(serUtilmd51a.Serialize(utilmd51a,“”).Root.CreateReader())作为XmlElement;
打破
案例
}

返回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"
Type Type=Type.GetType(“m_msgtype版本”);
对象myObject=Activator.CreateInstance(类型);//不需要对象,而是强制转换为特定类型
序列化程序serUtilmd51=新序列化程序();//不适用于“类型”

基本上,这里有三种选择(在没有动态的情况下);在反射中做所有事情,进行核心元编程,或者使用单一反射黑客跳转到通用方法。后者可能是您的最佳选择,因此:

步骤1:创建一个通用方法,该方法满足您的要求: 注意:您可以添加一个返回类型etc并从
.Invoke
捕获返回值。
.Invoke
调用中的前导
null
,在本例中是实例-
null
,因为它是一个
静态
方法;如果将方法设置为非静态,则将其替换为目标实例。如果将该方法设置为非公共,则需要在
GetMethod
调用中指定
BindingFlags

完整的工作示例:

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);
    }
}
使用系统;
类yourEnclosuringType
{
静态void Main()
{
Type Type=Type.GetType(“m_msgTypeVersion”);
对象[]args=null;//无args
typeof(yourEnclosuringType).GetMethod(“EvilHack”).MakeGenericMethod(类型)
.Invoke(null,args);
}
publicstaticvoidevilhack()
{
T myObject=Activator.CreateInstance();
Serializer serUtilmd51=新序列化程序();
serUtilmd51.DoIt(myObject);
}
}
类别m_msgTypeVersion//最差。名称曾经
{ }
类序列化程序
{
公共无效DoIt(T obj)
{
WriteLine(“我正在序列化”+obj);
}
}

请查看此相关问题您尝试执行的操作是不可能的,您无法在运行时解析泛型。@Ian oh,当然可以;这不是小事,但是是的:你可以“但是我需要将实例转换为特定的类而不是对象。”-确切的位置和原因是什么?@MarcGravel:是的,你可以“可能”做任何你想做的事情,尽管这可能归结为写你自己的IL。我不知道该怎么做,我想这可能不是解决问题的合适方法——但也许值得分享一个解决方案。@Ian fair;补充了一个答案:虽然我见过更糟糕的邪恶黑客:)
Type type = Type.GetType("m_msgTypeVersion");
typeof(YourEnclosingType).GetMethod("EvilHack").MakeGenericMethod(type)
            .Invoke(null, args);
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);
    }
}