【问题标题】:Can objects created with .net reflection be serialized?可以序列化使用 .net 反射创建的对象吗?
【发布时间】:2010-12-23 14:08:15
【问题描述】:

是否可以序列化通过反射创建的对象?尝试执行通过反射创建的对象的序列化时,出现“无法将类型为 'testNameSpace.ScreenClass' 的对象转换为类型 'testNameSpace.ScreenClass'”的错误。该错误没有意义,因为类型相同,因此强制转换应该成功。没有反射创建的对象的实例可以序列化OK。

编辑: 这是在我的原始帖子中没有正确呈现的代码

//Get the Assembly from file
 Assembly webAssembly = Assembly.LoadFile(@"C:\TestAssembly.exe");

 //Get the type from assembly
 Type screenType = webAssembly.GetType("testNameSpace.ScreenClass");

 //get the Constructor for the type (constructor does not take in parameters)
 ConstructorInfo ctor = screenType.GetConstructor(new Type[0]);

 //create an instance of the type
 object screen = ctor.Invoke(new object[] { });

 //get the "id" property of type
 PropertyInfo screenId = screenType.GetProperty("id");

 //populate the "id" property of the instance
 screenId.SetValue(screen, "1", null);

 Console.WriteLine("value of id property: " 
  + (string)screenId.GetValue(screen,null));

 //Attempt to serialize the instance of the object created through reflection
 try
 {
  FileStream fs = new FileStream("serialized.xml", FileMode.Create);
  XmlSerializer serializer = 
   new XmlSerializer(typeof(testNameSpace.ScreenClass));
  serializer.Serialize(fs, screen); //error occurs here
  fs.Close();
 }
 catch (Exception ex)
 {
  Console.WriteLine("Message: {0}\nInnerException: {1}\nStack Trace:\n{2}", 
   ex.Message, ex.InnerException.Message, ex.StackTrace);
 }

 //Now create instance of object without using reflection and serialize
 testNameSpace.ScreenClass screen2 = new testNameSpace.ScreenClass();
 screen2.id = "2";
 FileStream fs = new FileStream("serialized2.xml", FileMode.Create);
 XmlSerializer serializer 
  = new XmlSerializer(typeof(testNameSpace.ScreenClass));
 serializer.Serialize(fs, screen2);
 fs.Close();
 Console.WriteLine
  ("\nContents of serialized2.xml:\n" + File.ReadAllText("serialized2.xml"));

从控制台运行时的输出

Message: There was an error generating the XML document.
InnerException: Unable to cast object of type 'testNameSpace.ScreenClass' to type 'testNameSpace.ScreenClass'.
Stack Trace:
   at System.Xml.Serialization.XmlSerializer.Serialize(XmlWriter xmlWriter, Object o, XmlSerializerNamespaces namespaces, String encodingStyle, String id)
   at System.Xml.Serialization.XmlSerializer.Serialize(Stream stream, Object o, XmlSerializerNamespaces namespaces)
   at System.Xml.Serialization.XmlSerializer.Serialize(Stream stream, Object o)
   at Program.GetOneProperty() in C:\Code\Serialize.cs:line 96

Contents of serialized2.xml:
<?xml version="1.0"?>
<applicationScreensScreen xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" id="2" />

【问题讨论】:

    标签: .net xml reflection serialization


    【解决方案1】:

    Assembly.LoadFile() 方法是您的问题,它在错误的上下文中加载程序集。加载上下文有点难以理解,Suzanne Cook 在她的博客中谈到了它。当序列化程序需要该类型时,它将使用 Assembly.LoadFrom() 并再次加载程序集。现在它发现不匹配,来自不同程序集的类型永远不会相同。

    LoadFile() 仅在非常有限的情况下有用,如 MSDN 库文章的备注部分所述。您应该改用 Assembly.LoadFrom() 或 Load()。首选后者,因为它消除了从不同文件加载具有相同显示名称的程序集的可能性。如果由于程序集不在程序的探测路径中而导致问题(如果它存储在c:\ 中则不会),则执行 AppDomain.AssemblyResolve 事件处理程序以确保找到正确的文件。

    【讨论】:

    • 避免.NET程序集加载问题的秘诀:(1)使用Assembly.Load; (2) 如果您确定需要它,请使用 Assembly.LoadFrom; (3) 永远不要使用 Assembly.LoadFile
    • 感谢您清理我的原始帖子。提交后,我没有看到编辑帖子中错误的方法。显然有一种方法可以做到这一点,我只是没有看到。我能够在仍然使用 Assembly.LoadFile 的同时解决问题。如果我传递对象的一个​​实例而不是类型,那么就会发生序列化。 XmlSerializer 序列化器 = new XmlSerializer(typeof(testNameSpace.ScreenClass)); //error XmlSerializer serializer = new XmlSerializer(typeof(screen)); //有效
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-04
    • 1970-01-01
    • 1970-01-01
    • 2013-02-10
    • 2014-10-09
    • 1970-01-01
    • 2015-05-09
    相关资源
    最近更新 更多