標準フォーマッタを使用して既存のオブジェクトにデシリアライズします

通常のデシリアライゼーション.netは、常に新しいオブジェクトのグラフを作成します。 これは必ずしも便利ではありません。







検索ではすぐに答えが得られませんでした。 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<MemberInfo> deserializeMembers = new List<MemberInfo>(members.Length); List<object> data = new List<object>(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; } }
      
      







デシリアライズするときは、バインダーをインストールする必要があります。これにより、既存のオブジェクトにデシリアライズ用のラッパーが作成されます。



  BinaryFormatter bf = new BinaryFormatter(null, context); bf.Binder = new RealObjectBinder(YourType.Assembly.FullName, YourType.FullName); bf.Deserialize(memStream);
      
      






All Articles