【问题标题】:How to serialize/deserialize an object loaded from another assembly?如何序列化/反序列化从另一个程序集加载的对象?
【发布时间】:2012-01-01 07:08:42
【问题描述】:

我想序列化/反序列化一个已被从程序集中加载的另一个对象实例化的对象:

Interfaces.cs(来自引用的程序集,Interfaces.dll)

public interface ISomeInterface
{
 ISettings Settings { get; set; }
}

public interface ISettings : ISerializable
{
 DateTime StartDate { get; }
}

SomeClass.cs(来自引用的程序集,SomeClass.dll)

public class SomeClass : ISomeInterface
{
 private MySettings settings = new Settings();

 public ISettings Settings
 {
  get { return (ISettings)settings; }
  set { settings = value as MySettings; }
 }
}

[Serializable]
public class MySettings : ISettings
{
 private DateTime dt;

 public MySettings() { dt = DateTime.Now; }

 protected MySettings(SerializationInfo info, StreamingContext context)
 {
  dt = info.GetDateTime("dt");
 }

 [SecurityPermissionAttribute(SecurityAction.Demand, SerializationFormatter = true)]
 public void GetObjectData(SerializationInfo info, StreamingContext context)
 {
  info.AddValue("dt", dt);
 }

 public DateTime StartDate
 {
  get { return startFrom; }
  internal set { startFrom = value; }
 }
}

启动项目:

[Serializable]
public class ProgramState
}
 public ISettings Settings { get; set; }
}

在启动项目中,最终我将 ProgramState 的一个实例的 Settings 设置为 SomeClass 的 Settings。然后我继续使用以下方法进行序列化:

public void SerializeState(string filename, ProgramState ps)
{
 Stream s = File.Open(filename, FileMode.Create);
 BinaryFormatter bFormatter = new BinaryFormatter();
 bFormatter.Serialize(s, ps);
 s.Close();
}

这不会引发任何异常。我反序列化:

public ProgramState DeserializeState(string filename)
{
 if (File.Exists(filename))
 {
  ProgramState res = new ProgramState();
  Stream s = File.Open(filename, FileMode.Open);
  BinaryFormatter bFormatter = new BinaryFormatter();
  try
  {
   res = (ProgramState)bFormatter.Deserialize(s);
  }
  catch (SerializationException se)
  {
   Debug.WriteLine(se.Message);
  }
  s.Close();
  return res;
 }
 else return new ProgramState();
}

这会引发异常,并且在我的调试输出中出现以下内容:

在 mscorlib.dll 中发生了“System.Runtime.Serialization.SerializationException”类型的第一次机会异常
找不到程序集 'SomeClass, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'。

我确定在调用 DeserializeState 之前已经加载了包含 SomeClass 的程序集,那么为什么它会抛出无法找到它的异常呢?

我一直在看一些教程,但我只能找到处理来自同一程序集的类的教程(另外,我对 .NET 中的序列化和反序列化过程的了解很少 - 一个详细的链接解释可能会有所帮助)。

与此同时,有什么方法可以正确反序列化 MySettings 对象?

【问题讨论】:

  • 使用 fuslogvw.exe 解决程序集解析问题。永远不要使用 Assembly.LoadFile()。
  • 我运行了您发布的代码,一切正常。在我看来,如果 SomeClass.dll 没有被加载,代码会在反序列化之前中断。是否所有项目都针对相同的 .NET 框架版本?
  • @Hans,谢谢,我会调查一下。
  • @Filip,是的,应用程序需要与 .NET Framework 3.5 兼容,并且所有项目都设置为该版本。我正在使用 System.ComponentModel.Composition 加载程序集,所有项目(不需要它的接口库除外)都包含对定义该命名空间的同一 DLL 文件的引用。

标签: c# serialization deserialization


【解决方案1】:

在浏览了更多内容(即谷歌搜索答案)之后,我能够解决这个问题。这是修改后的代码:

Interfaces.cs(来自引用的程序集,Interfaces.dll)

public interface ISomeInterface
{
 ISettings Settings { get; set; }
}

public interface ISettings
{
 DateTime StartDate { get; }
}

SomeClass.cs(来自引用的程序集,SomeClass.dll)

public class SomeClass : ISomeInterface
{
 private MySettings settings = new Settings();

 public ISettings Settings
 {
  get { return (ISettings)settings; }
  set { settings = value as MySettings; }
 }
}

[Serializable]
public class MySettings : ISettings
{
 private DateTime dt;

 public MySettings() { dt = DateTime.Now; }

 public DateTime StartDate
 {
  get { return startFrom; }
  internal set { startFrom = value; }
 }
}

序列化是通过:

public void SerializeState(string filename, ProgramState ps)
{
 Stream s = File.Open(filename, FileMode.Create);
 BinaryFormatter bFormatter = new BinaryFormatter();
 bFormatter.AssemblyFormat =
    System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Simple;
 bFormatter.Serialize(s, ps);
 s.Close();
}

反序列化:

public ProgramState DeserializeState(string filename)
{
 if (File.Exists(filename))
 {
  ProgramState res = new ProgramState();
  Stream s = File.Open(filename, FileMode.Open);
  BinaryFormatter bFormatter = new BinaryFormatter();
  bFormatter.AssemblyFormat =
    System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Simple;
  bFormatter.Binder = new MyBinder(); // MyBinder class code given below
  try
  {
   res = (ProgramState)bFormatter.Deserialize(s);
  }
  catch (SerializationException se)
  {
   Debug.WriteLine(se.Message);
  }
  s.Close();
  return res;
 }
 else return new ProgramState();
}

已添加此类。这是二进制格式化程序的活页夹:

internal sealed class MyBinder : SerializationBinder
{
 public override Type BindToType(string assemblyName, string typeName)
 {
  Type ttd = null;
  try
  {
   string toassname = assemblyName.Split(',')[0];
   Assembly[] asmblies = AppDomain.CurrentDomain.GetAssemblies();
   foreach (Assembly ass in asmblies)
   {
    if (ass.FullName.Split(',')[0] == toassname)
    {
     ttd = ass.GetType(typeName);
     break;
    }
   }
  }
  catch (System.Exception e)
  {
   Debug.WriteLine(e.Message);
  }
  return ttd;
 }
}

【讨论】:

  • 这是需要反序列化的对象类型。如果需要通用性,您可以将其替换为您自己的类型或 Object。
【解决方案2】:

您想(反)使用二进制格式进行序列化吗? 如果没有,您可以使用以下内容:

附:这不是解决方案,而是某种解决方法。

一些组装

公共接口 ISomeInterface { ISettings 设置 { 获取;放; } }

public interface ISettings : ISerializable
{
    DateTime StartDate { get; }
}

public class SerializeHelper<T>
{
    public static void Serialize(string path, T item)
    {
        var serializer = new XmlSerializer(typeof(T));
        using (TextWriter textWriter = new StreamWriter(path, false, Encoding.UTF8))
        {
            serializer.Serialize(textWriter, T item);
        }
    }
}

SerializeHelper.Serialize(@"%temp%\sample.xml", instanceOfISomeInterface);

其他一些程序集

public interface ISomeOtherInterface
{
ISettings Settings { get; set; }
}

public class DeSerializeHelper<T>
{
    public static T Deserialize(string path)
    {
   T instance = default(T);
   var serializer = new XmlSerializer(typeof(TestData));
   using (TextReader r = new StreamReader(path, Encoding.UTF8))
   {
      instance = (T)serializer.Deserialize(r);
   }
   return instance;
    }
}

ISomeOtherInterface instance = DeSerializeHelper.Deserialize<SomeOtherInterfaceImplementation>(@"%temp%\sample.xml")

【讨论】:

  • 嗨,VMykyt。感谢您的努力,但我确实需要它的二进制文件。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-24
  • 1970-01-01
  • 2022-12-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多