Как сериализовать/десериализовать объект, загруженный из другой сборки?

Я хочу сериализовать/десериализовать объект, который был создан другим объектом, загруженным из сборки:

Интерфейсы .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 в настройках SomeClass. Затем я продолжу сериализацию, используя:

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

Это не исключает никаких исключений. Я deserialize с:

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

Это генерирует исключение, и на моем выходе Debug появляется следующее:

В mscorlib.dll произошла первая случайная ошибка типа "System.Runtime.Serialization.SerializationException" Не удалось найти сборку "SomeClass, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = null".

Я уверен, что сборка, содержащая SomeClass, была загружена до вызова DeserializeState, так почему же она бросает исключение, которое не может найти?

Я изучал некоторые учебные пособия, но те, которые мне удалось найти, касались только классов из одной и той же сборки (плюс, мое понимание процесса сериализации и десериализации в .NET минимально - ссылка на подробный объяснение может быть полезно).

Тем временем, есть ли способ сделать это правильно десериализовать объект MySettings?

Ответ 1

После того, как выкарабкались еще несколько (т.е. отыграли ответ), я смог это разрешить. Вот модифицированный код:

Интерфейсы .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;
 }
}

Ответ 2

Вы хотите (де) сериализовать, используя двоичный формат? Если нет, вы можете использовать следующее:

P.S. Это не решение, а какое-то обходное решение.

Некоторая сборка

открытый интерфейс ISomeInterface  {   Настройки ISettings {get; задавать; }   }

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")