Навигация
Главная »  Новости 

Deserialize в существующие объекты используя стандартный форматер


Источник: habrahabr
mdaemon
Штатная десериализация .net всегда создает граф новых объектов. Это не всегда удобно. 
  • Например если объекты содержат несериализуемые данные, открытые хэндлы и прочее.
  • Объекты не попадающие в сериализацию могут иметь ссылки на зачитываемые объекты и т.п. Особенно это актуально, если ваша сборка используется еще кем то, и вы не можете решить все подобные случаи при помощи правильного дизайна.
  • И в конце концов, ради небольшого Undo полностью пересоздавать объекты нерационально.
Поиск не дал готового ответа. Есть не самые простые решения с использованием protobuf и прочих сторонних сериализаторов, но это не всегда применимо. Задача в целом несложная, и мое решение не является чем то выдающимся, но с другой стороны, тем кто впервые столкнется с похожей проблемой - будет проще. Сериализация делается как обычно. Следующие 2 класса решат проблему при десериализации.
 [Serializable] public class RealObjectHelper : IObjectReference, ISerializable { Object m_realObject; virtual object getObject(ObjectId id) { //Этот метод должен возвращать ваш объект, return id.GetObject(); } public RealObjectHelper(SerializationInfo info, StreamingContext context) { ObjectId id = (ObjectId)info.GetValue("ID", typeof(ObjectId)); m_realObject = getObject(id); if(m_realObject == null) return; Type t = m_realObject.GetType(); MemberInfo[] members = FormatterServices.GetSerializableMembers(t, context); List deserializeMembers = new List(members.Length); List data = new List(members.Length); foreach(MemberInfo mi in members) { Type dataType = null; if(mi.MemberType == MemberTypes.Field) { FieldInfo fi = mi as FieldInfo; dataType = fi.FieldType; } else if(mi.MemberType == MemberTypes.Property){ PropertyInfo pi = mi as PropertyInfo; dataType = pi.PropertyType; } try { if(dataType != null){ data.Add(info.GetValue(mi.Name, dataType)); deserializeMembers.Add(mi); } } catch (SerializationException) { //some fiels are missing, new version, skip this fields } } FormatterServices.PopulateObjectMembers(m_realObject, deserializeMembers.ToArray(), data.ToArray()); }  public object GetRealObject( StreamingContext context ) { return m_realObject; } [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)] public void GetObjectData(SerializationInfo info, StreamingContext context) { } }  public class RealObjectBinder: SerializationBinder { String assemVer; String typeVer; public RealObjectBinder(String asmName, String typeName) { assemVer = asmName; typeVer = typeName; } public override Type BindToType( String assemblyName, String typeName ) { Type typeToDeserialize = null; if ( assemblyName.Equals( assemVer ) && typeName.Equals( typeVer ) ) { return typeof(RealObjectHelper); } typeToDeserialize = Type.GetType( String.Format(  "{0}, {1}", typeName, assemblyName ) ); return typeToDeserialize; } }  При десериализации надо установить Binder, который создаст обертку для десериализации в ваш существующий объект. 
    BinaryFormatter bf = new BinaryFormatter(null, context); bf.Binder = new RealObjectBinder(YourType.Assembly.FullName, YourType.FullName); bf.Deserialize(memStream);


 

 Создание системы отчетов для работы финансового директора на основе ERP системы и Seagate Crystal Reports 8.0.
 Компьютер и спина.
 Сертификационная программа (ISC)2.
 Информационная безопасность и интернет будущего.
 Новые технологии VMware автоматизируют оптовую сдачу облаков в аренду.


Главная »  Новости 

© 2017 Team.Furia.Ru.
Частичное копирование материалов разрешено.