Бинарная сериализация COM-объектов

143
16 января 2021, 09:50

Как правильно перевести в массив байт COM-объект и/или объекты, к классам которым нельзя получить доступ и поставить им атрибут Serializable (например, из сторонних библиотек)?

Answer 1

Например надо сериализовать следующие классы:

class SampleClass1
{
    public int SampleField1 { get; set; }
    public string SampleField2 { get; set; }
    public SampleClass2 SampleField3 { get; set; }
}
class SampleClass2
{
    public int SampleField1 { get; set; }
    public string SampleField2 { get; set; }
}

Вариант 1:

class Serializer1
{
    [Serializable]
    private class SampleClassProxy : ISerializable
    {
        public readonly SampleClass1 Obj;
        public SampleClassProxy()
        {
            Obj = new SampleClass1();
        }
        public SampleClassProxy(SampleClass1 obj)
        {
            Obj = obj;
        }
        public SampleClassProxy(SerializationInfo info, StreamingContext context)
        {
            Obj = new SampleClass1() {
                SampleField1 = info.GetInt32("SampleField1"),
                SampleField2 = info.GetString("SampleField2"),
                SampleField3 = new SampleClass2() {
                    SampleField1 = info.GetInt32("SampleField3.SampleField1"),
                    SampleField2 = info.GetString("SampleField3.SampleField2")
                }
            };
        }
        public void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            info.AddValue("SampleField1", Obj.SampleField1);
            info.AddValue("SampleField2", Obj.SampleField2);
            info.AddValue("SampleField3.SampleField1", Obj.SampleField3.SampleField1);
            info.AddValue("SampleField3.SampleField2", Obj.SampleField3.SampleField2);
        }
    }
    public static void DoWork()
    {
        var obj = new SampleClass1() {
            SampleField1 = 1,
            SampleField2 = "2",
            SampleField3 = new SampleClass2() {
                SampleField1 = 3,
                SampleField2 = "4"
            }
        };
        var proxy = new SampleClassProxy(obj);
        var formatter = new BinaryFormatter();
        var bytes = Serialize(formatter, proxy);
        var proxy2 = Deserialize(formatter, bytes);
        var obj2 = proxy2.Obj;
    }
    private static byte[] Serialize(IFormatter formatter, SampleClassProxy obj)
    {
        using (var stream = new MemoryStream()) {
            formatter.Serialize(stream, obj);
            return stream.ToArray();
        }
    }
    private static SampleClassProxy Deserialize(IFormatter formatter, byte[] bytes)
    {
        using (var stream = new MemoryStream(bytes)) {
            return (SampleClassProxy)formatter.Deserialize(stream);
        }
    }
}

Вариант 2:

class Serializer2
{
    private class SampleClass1Surrogate : ISerializationSurrogate
    {
        public void GetObjectData(object obj, SerializationInfo info, StreamingContext context)
        {
            var sampleClass = (SampleClass1)obj;
            info.AddValue("SampleField1", sampleClass.SampleField1);
            info.AddValue("SampleField2", sampleClass.SampleField2);
            info.AddValue("SampleField3", sampleClass.SampleField3);
        }
        public object SetObjectData(object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector)
        {
            var sampleClass = (SampleClass1)obj;
            sampleClass.SampleField1 = info.GetInt32("SampleField1");
            sampleClass.SampleField2 = info.GetString("SampleField2");
            sampleClass.SampleField3 = (SampleClass2)info.GetValue("SampleField3", typeof(SampleClass2));
            return sampleClass;
        }
    }
    private class SampleClass2Surrogate : ISerializationSurrogate
    {
        public void GetObjectData(object obj, SerializationInfo info, StreamingContext context)
        {
            var sampleClass = (SampleClass2)obj;
            info.AddValue("SampleField1", sampleClass.SampleField1);
            info.AddValue("SampleField2", sampleClass.SampleField2);
        }
        public object SetObjectData(object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector)
        {
            var sampleClass = (SampleClass2)obj;
            sampleClass.SampleField1 = info.GetInt32("SampleField1");
            sampleClass.SampleField2 = info.GetString("SampleField2");
            return sampleClass;
        }
    }
    public static void DoWork()
    {
        var obj = new SampleClass1() {
            SampleField1 = 1,
            SampleField2 = "2",
            SampleField3 = new SampleClass2() {
                SampleField1 = 3,
                SampleField2 = "4"
            }
        };
        IFormatter formatter = new BinaryFormatter();
        var surrogateSelector = new SurrogateSelector();
        surrogateSelector.AddSurrogate(typeof(SampleClass1), new StreamingContext(StreamingContextStates.All), new SampleClass1Surrogate());
        surrogateSelector.AddSurrogate(typeof(SampleClass2), new StreamingContext(StreamingContextStates.All), new SampleClass2Surrogate());
        formatter.SurrogateSelector = surrogateSelector;
        var bytes = Serialize(formatter, obj);
        var obj2 = Deserialize(formatter, bytes);
    }
    private static byte[] Serialize(IFormatter formatter, SampleClass1 obj)
    {
        using (var stream = new MemoryStream()) {
            formatter.Serialize(stream, obj);
            return stream.ToArray();
        }
    }
    private static SampleClass1 Deserialize(IFormatter formatter, byte[] bytes)
    {
        using (var stream = new MemoryStream(bytes)) {
            return (SampleClass1)formatter.Deserialize(stream);
        }
    }
}
READ ALSO
Работа с картами и GPS на сайте

Работа с картами и GPS на сайте

Есть сайт написанный на ASPNET MVC

141
AngleSharp не удается получить данные сайта

AngleSharp не удается получить данные сайта

Простейший пример, взят с сайта библиотеки

130
Как проверить ключ на равенство со значением Dictionary, listbox C#

Как проверить ключ на равенство со значением Dictionary, listbox C#

Всем приветПомогите пожалуйста с Dictionary

116