Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Serializing anonymous types

I'd like to convert anonymous type variable to byte[], how can I do that?

What I tried:

byte[] result;

var my = new
{
    Test = "a1",
    Value = 0
};

BinaryFormatter bf = new BinaryFormatter();

using (MemoryStream ms = new MemoryStream())
{
    bf.Serialize(ms, my); //-- ERROR

    result = ms.ToArray();
}

I've got error:

An exception of type 'System.Runtime.Serialization.SerializationException' occurred in mscorlib.dll but was not handled in user code

Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]' in Assembly 'MyProject, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' is not marked as serializable.Additional information: Type '<>f__AnonymousType10`2[[System.String, mscorlib,

Can somebody help me? What I'm doing wrong? Or this is not possible to do?

like image 568
user3018896 Avatar asked Sep 09 '16 07:09

user3018896


People also ask

What are anonymous types in Linq?

Anonymous types typically are used in the select clause of a query expression to return a subset of the properties from each object in the source sequence. For more information about queries, see LINQ in C#. Anonymous types contain one or more public read-only properties.

What are difference between anonymous and dynamic types?

Anonymous type is a class type that contain one or more read only properties whereas dynamic can be any type it may be any type integer, string, object or class. Anonymous types are assigned types by the compiler. Anonymous type is directly derived from System.

What is the difference between tuples and anonymous types?

The ValueTuple types are mutable, whereas Tuple are read-only. Anonymous types can be used in expression trees, while tuples cannot.

What types are serializable C#?

The following types built into the . NET Framework can all be serialized and are considered to be primitive types: Byte, SByte, Int16, Int32, Int64, UInt16, UInt32, UInt64, Single, Double, Boolean, Char, Decimal, Object, and String.


3 Answers

Just create a serializable class

[Serializable]
class myClass
{
    public string Test { get; set; }
    public int Value { get; set; }
}

And you can serialize your object the following way:

byte[] result;
myClass my = new myClass()
{
    Test = "a1",
    Value = 0
};
BinaryFormatter bf = new BinaryFormatter();
using (MemoryStream ms = new MemoryStream())
{
    bf.Serialize(ms, my); //NO MORE ERROR
    result = ms.ToArray();
}

But i'ts not possible to serialize a anonymous type

like image 100
fubo Avatar answered Sep 25 '22 23:09

fubo


Types that are to be serialized with the default serializer family (XmlSerializer, BinaryFormatter, DataContractSerializer, ...) need to be marked [Serializable], need to be public types, and will require public read-write properties.

Anonymous types don't fulfill this role, because they have none of the required properties.

Just create a type that does, and serialize that instead.

like image 45
CodeCaster Avatar answered Sep 22 '22 23:09

CodeCaster


Firstly: the correct approach is, as others have pointed out, to create a proper class for serialization.

However, it is actually possible to serialize an anonymous object using Json.Net. Note that I do not recommend actually doing this in a real project - it's a curiosity only.

This code relies on a sneaky way of accessing the underlying type of an anonymous object by using an exemplar object as a type holder:

using System;
using System.IO;
using Newtonsoft.Json;
using Newtonsoft.Json.Bson;

public class Program
{
    static void Main()
    {
        var data = serializeAnonymousObject();
        deserializeAnonymousObject(data);
    }

    static byte[] serializeAnonymousObject()
    {
        // This is in a separate method to demonstrate that you can
        // serialize in one place and deserialize in another.

        var my = new
        {
            Test  = "a1",
            Value = 12345
        };

        return Serialize(my);
    }

    static void deserializeAnonymousObject(byte[] data)
    {
        // This is in a separate method to demonstrate that you can
        // serialize in one place and deserialize in another.

        var deserialized = new  // Used as a type holder
        {
            Test  = "",
            Value = 0
        };

        deserialized = Deserialize(deserialized, data);

        Console.WriteLine(deserialized.Test);
        Console.WriteLine(deserialized.Value);
    }

    public static byte[] Serialize(object obj)
    {
        using (var ms     = new MemoryStream())
        using (var writer = new BsonWriter(ms))
        {
            new JsonSerializer().Serialize(writer, obj);
            return ms.ToArray();
        }
    }

    public static T Deserialize<T>(T typeHolder, byte[] data)
    {
        using (var ms     = new MemoryStream(data))
        using (var reader = new BsonReader(ms))
        {
            return new JsonSerializer().Deserialize<T>(reader);
        }
    }
}
like image 23
Matthew Watson Avatar answered Sep 26 '22 23:09

Matthew Watson