Most of the user-defined classes going through the Ignite .NET API will be passed over the wire to other grid nodes. These classes include:
ICacheEntryProcessor
, ICacheEntryFilter
, ICacheEntryEventFilter
, ICacheEntryEventListener
)IComputeFunc
), actions (IComputeAction
) and jobs (IComputeJob
)IService
)IEventListener
, IEventFilter
, IMessageListener
)Passing objects of these classes over the wire requires serialization. Ignite .NET supports the following ways of serializing user data:
Apache.Ignite.Core.Binary.IBinarizable
interfaceApache.Ignite.Core.Binary.IBinarySerializer
interfaceSystem.Runtime.Serialization.ISerializable
interface🚧Ignite.NET 2.0 does not require registering types in
BinaryConfigurations
Previous Ignite.NET versions (1.9 and earlier) required all types except
[Serializable]
to be registered inIgniteConfiguration.BinaryConfiguration
. This is no longer needed in Ignite.NET 2.0 and later versions.
🚧Ignite.NET 2.0 allows SQL over
Serializable
typesSince version 2.0, all serialization is performed in Ignite Binary Format which enables all Ignite features like SQL and Binary Mode. This includes
[Serializable]
types with and withoutISerializable
interface.
👍Automatic GetHashCode and Equals Implementation
If an object can be serialized into a binary form, then Ignite will calculate its hash code during serialization and write it to the resulting binary array. Also, Ignite provides a custom implementation of the equals method for the binary object's comparison needs. This means that you do not need to override the
GetHashCode
andEquals
methods of your custom keys and values in order for them to be used in Ignite.
IBinarizable
approach provides a fine-grained control over serialization. This is a preferred way for high-performance production code.
First, implement IBinarizable
interface in your class:
public class Address : IBinarizable
{
public string Street { get; set; }
public int Zip { get; set; }
public void WriteBinary(IBinaryWriter writer)
{
// Alphabetic field order is required for SQL DML to work.
// Even if DML is not used, alphabetic order is recommended.
writer.WriteString("street", Street);
writer.WriteInt("zip", Zip);
}
public void ReadBinary(IBinaryReader reader)
{
// Read order does not matter, however, reading in the same order
// as writing improves performance.
Street = reader.ReadString("street");
Zip = reader.ReadInt("zip");
}
}
IBinarizable
can also be implemented in raw mode, without field names. This provides the fastest and the most compact serialization, but disables SQL queries:
public class Address : IBinarizable
{
public string Street { get; set; }
public int Zip { get; set; }
public void WriteBinary(IBinaryWriter writer)
{
var rawWriter = writer.GetRawWriter();
rawWriter.WriteString(Street);
rawWriter.WriteInt(Zip);
}
public void ReadBinary(IBinaryReader reader)
{
// Read order must be the same as write order
var rawReader = reader.GetRawReader();
Street = rawReader.ReadString();
Zip = rawReader.ReadInt();
}
}
IBinarySerializer
is similar to IBinarizable
, but separates serialization logic from the class implementation. This may be useful when the class code can not be modified, and serialization logic is shared between multiple classes, etc. The following code yields exactly the same serialization as in Address
example above:
public class Address : IBinarizable
{
public string Street { get; set; }
public int Zip { get; set; }
}
public class AddressSerializer : IBinarySerializer
{
public void WriteBinary(object obj, IBinaryWriter writer)
{
var addr = (Address) obj;
writer.WriteString("street", addr.Street);
writer.WriteInt("zip", addr.Zip);
}
public void ReadBinary(object obj, IBinaryReader reader)
{
var addr = (Address) obj;
addr.Street = reader.ReadString("street");
addr.Zip = reader.ReadInt("zip");
}
}
Serializer should be specified in the configuration like this:
var cfg = new IgniteConfiguration
{
BinaryConfiguration = new BinaryConfiguration
{
TypeConfigurations = new[]
{
new BinaryTypeConfiguration(typeof (Address))
{
Serializer = new AddressSerializer()
}
}
}
};
using (var ignite = Ignition.Start(cfg))
{
...
}
Types implementing the System.Runtime.Serialization.ISerializable
interface will be serialized accordingly (by calling GetObjectData
and serialization constructor). All system features are supported: IObjectReference
, IDeserializationCallback
, OnSerializingAttribute
, OnSerializedAttribute
, OnDeserializingAttribute
, OnDeserializedAttribute
.
GetObjectData
result is written in Ignite binary format. The following three classes provide identical serialized representation:
class Reflective
{
public int Id { get; set; }
public string Name { get; set; }
}
class Binarizable : IBinarizable
{
public int Id { get; set; }
public string Name { get; set; }
public void WriteBinary(IBinaryWriter writer)
{
writer.WriteInt("Id", Id);
writer.WriteString("Name", Name);
}
public void ReadBinary(IBinaryReader reader)
{
Id = reader.ReadInt("Id");
Name = reader.ReadString("Name");
}
}
class Serializable : ISerializable
{
public int Id { get; set; }
public string Name { get; set; }
public Serializable() {}
protected Serializable(SerializationInfo info, StreamingContext context)
{
Id = info.GetInt32("Id");
Name = info.GetString("Name");
}
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("Id", Id);
info.AddValue("Name", Name);
}
}
Ignite reflective serialization is essentially an IBinarizable
approach where the interface is implemented automatically by reflecting over all fields and emitting write/read calls.
There are no requirements for this mechanism, any class or struct can be serialized (including all system types, delegates, expression trees, anonymous types, etc).
Use [NonSerialized]
attribute to exclude unwanted fields.
Raw mode can be enabled by specifying BinaryReflectiveSerializer
explicitly:
var binaryConfiguration = new BinaryConfiguration
{
TypeConfigurations = new[]
{
new BinaryTypeConfiguration(typeof(MyClass))
{
Serializer = new BinaryReflectiveSerializer {RawMode = true}
}
}
};
<igniteConfiguration>
<binaryConfiguration>
<typeConfigurations>
<binaryTypeConfiguration typeName='Apache.Ignite.ExamplesDll.Binary.Address'>
<serializer type='Apache.Ignite.Core.Binary.BinaryReflectiveSerializer, Apache.Ignite.Core' rawMode='true' />
</binaryTypeConfiguration>
</typeConfigurations>
</binaryConfiguration>
</igniteConfiguration>
Otherwise, BinaryConfiguration
is not required.
Performance is identical to manual IBinarizable. Reflection is only used on startup to iterate over the fields and emit efficient IL code.
Types marked with [Serializable]
attribute but without ISerializable
interface are written with Ignite reflective serializer.
Entity Framework POCOs can be used directly with Ignite.
However, POCO proxies (https://msdn.microsoft.com/en-us/data/jj592886.aspx) cannot be directly serialized or deserialized by Ignite, because the proxy type is a dynamic type.
Make sure to disable proxy creation when using EF objects with Ignite:
ctx.Configuration.ProxyCreationEnabled = false;
ctx.ContextOptions.ProxyCreationEnabled = false;
See Ignite Serialization Performance blog post for more details on serialization performance in various modes.
Updated almost 6 years ago
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4