IGNITE-1419 .Net: Added optional "raw" flag to binary type configuration. This closes #376.
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/cba4f4c0 Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/cba4f4c0 Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/cba4f4c0 Branch: refs/heads/ignite-1786 Commit: cba4f4c039013a79e50078a92cc2df761156c66f Parents: 2d38eb8 Author: Pavel Tupitsyn <[email protected]> Authored: Thu Mar 3 09:58:40 2016 +0300 Committer: vozerov-gridgain <[email protected]> Committed: Thu Mar 3 09:58:40 2016 +0300 ---------------------------------------------------------------------- .../utils/PlatformConfigurationUtils.java | 6 +- .../Binary/BinarySelfTest.cs | 110 ++-- .../Apache.Ignite.Core.csproj | 2 +- .../Binary/BinaryReflectiveSerializer.cs | 241 ++++++++ .../Multicast/TcpDiscoveryMulticastIpFinder.cs | 2 +- .../Impl/Binary/BinaryReflectiveActions.cs | 576 +++++++++++++------ .../Impl/Binary/BinaryReflectiveSerializer.cs | 218 ------- .../Impl/Binary/BinaryWriter.cs | 28 +- 8 files changed, 749 insertions(+), 434 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/cba4f4c0/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformConfigurationUtils.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformConfigurationUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformConfigurationUtils.java index 32ab812..c0e9f1b 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformConfigurationUtils.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformConfigurationUtils.java @@ -594,10 +594,10 @@ import java.util.Map; w.writeInt(multiFinder.getAddressRequestAttempts()); w.writeInt(multiFinder.getResponseWaitTime()); - Integer ttl = multiFinder.getTimeToLive(); - w.writeBoolean(ttl != null); + int ttl = multiFinder.getTimeToLive(); + w.writeBoolean(ttl != -1); - if (ttl != null) + if (ttl != -1) w.writeInt(ttl); } } http://git-wip-us.apache.org/repos/asf/ignite/blob/cba4f4c0/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinarySelfTest.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinarySelfTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinarySelfTest.cs index f49a28a..24ce3c8 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinarySelfTest.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinarySelfTest.cs @@ -727,16 +727,22 @@ namespace Apache.Ignite.Core.Tests.Binary * <summary>Check write of primitive fields through reflection.</summary> */ [Test] - public void TestPrimitiveFieldsReflective() + public void TestPrimitiveFieldsReflective([Values(false, true)] bool raw) { - ICollection<BinaryTypeConfiguration> typeCfgs = - new List<BinaryTypeConfiguration>(); - - typeCfgs.Add(new BinaryTypeConfiguration(typeof(PrimitiveFieldType))); + var serializer = new BinaryReflectiveSerializer {RawMode = raw}; - BinaryConfiguration cfg = new BinaryConfiguration {TypeConfigurations = typeCfgs}; + Assert.AreEqual(raw, serializer.RawMode); - Marshaller marsh = new Marshaller(cfg); + var marsh = new Marshaller(new BinaryConfiguration + { + TypeConfigurations = new[] + { + new BinaryTypeConfiguration(typeof (PrimitiveFieldType)) + { + Serializer = serializer + } + } + }); PrimitiveFieldType obj = new PrimitiveFieldType(); @@ -927,15 +933,21 @@ namespace Apache.Ignite.Core.Tests.Binary * <summary>Check write of object with enums.</summary> */ [Test] - public void TestEnumsReflective() + public void TestEnumsReflective([Values(false, true)] bool raw) { Marshaller marsh = new Marshaller(new BinaryConfiguration { TypeConfigurations = new[] { - new BinaryTypeConfiguration(typeof (EnumType)), + new BinaryTypeConfiguration(typeof (EnumType)) + { + Serializer = new BinaryReflectiveSerializer {RawMode = raw} + }, new BinaryTypeConfiguration(typeof (TestEnum)) + { + Serializer = new BinaryReflectiveSerializer {RawMode = raw} + } } }); @@ -951,18 +963,26 @@ namespace Apache.Ignite.Core.Tests.Binary Assert.AreEqual(obj.GetHashCode(), portObj.GetHashCode()); - // Test enum field in binary form - var binEnum = portObj.GetField<IBinaryObject>("PEnum"); - Assert.AreEqual(obj.PEnum.GetHashCode(), binEnum.GetHashCode()); - Assert.AreEqual((int) obj.PEnum, binEnum.EnumValue); - Assert.AreEqual(obj.PEnum, binEnum.Deserialize<TestEnum>()); - Assert.AreEqual(obj.PEnum, binEnum.Deserialize<object>()); - Assert.AreEqual(typeof(TestEnum), binEnum.Deserialize<object>().GetType()); - Assert.AreEqual(null, binEnum.GetField<object>("someField")); - Assert.IsFalse(binEnum.HasField("anyField")); + if (!raw) + { + // Test enum field in binary form + var binEnum = portObj.GetField<IBinaryObject>("PEnum"); + Assert.AreEqual(obj.PEnum.GetHashCode(), binEnum.GetHashCode()); + Assert.AreEqual((int) obj.PEnum, binEnum.EnumValue); + Assert.AreEqual(obj.PEnum, binEnum.Deserialize<TestEnum>()); + Assert.AreEqual(obj.PEnum, binEnum.Deserialize<object>()); + Assert.AreEqual(typeof (TestEnum), binEnum.Deserialize<object>().GetType()); + Assert.AreEqual(null, binEnum.GetField<object>("someField")); + Assert.IsFalse(binEnum.HasField("anyField")); - var binEnumArr = portObj.GetField<IBinaryObject[]>("PEnumArray"); - Assert.IsTrue(binEnumArr.Select(x => x.Deserialize<TestEnum>()).SequenceEqual(obj.PEnumArray)); + var binEnumArr = portObj.GetField<IBinaryObject[]>("PEnumArray"); + Assert.IsTrue(binEnumArr.Select(x => x.Deserialize<TestEnum>()).SequenceEqual(obj.PEnumArray)); + } + else + { + Assert.IsFalse(portObj.HasField("PEnum")); + Assert.IsFalse(portObj.HasField("PEnumArray")); + } EnumType newObj = portObj.Deserialize<EnumType>(); @@ -974,14 +994,20 @@ namespace Apache.Ignite.Core.Tests.Binary * <summary>Check write of object with collections.</summary> */ [Test] - public void TestCollectionsReflective() + public void TestCollectionsReflective([Values(false, true)] bool raw) { var marsh = new Marshaller(new BinaryConfiguration { - TypeConfigurations = new List<BinaryTypeConfiguration> + TypeConfigurations = new[] { - new BinaryTypeConfiguration(typeof (CollectionsType)), + new BinaryTypeConfiguration(typeof (CollectionsType)) + { + Serializer = new BinaryReflectiveSerializer {RawMode = raw} + }, new BinaryTypeConfiguration(typeof (InnerObjectType)) + { + Serializer = new BinaryReflectiveSerializer {RawMode = raw} + } } }); @@ -1043,29 +1069,39 @@ namespace Apache.Ignite.Core.Tests.Binary * <summary>Check write of object fields through reflective serializer.</summary> */ [Test] - public void TestObjectReflective() + public void TestObjectReflective([Values(false, true)] bool raw) { - ICollection<BinaryTypeConfiguration> typeCfgs = - new List<BinaryTypeConfiguration>(); - - typeCfgs.Add(new BinaryTypeConfiguration(typeof(OuterObjectType))); - typeCfgs.Add(new BinaryTypeConfiguration(typeof(InnerObjectType))); - - BinaryConfiguration cfg = new BinaryConfiguration(); - - cfg.TypeConfigurations = typeCfgs; - - Marshaller marsh = new Marshaller(cfg); + var marsh = new Marshaller(new BinaryConfiguration + { + TypeConfigurations = new[] + { + new BinaryTypeConfiguration(typeof (OuterObjectType)) + { + Serializer = new BinaryReflectiveSerializer {RawMode = raw} + }, + new BinaryTypeConfiguration(typeof (InnerObjectType)) + { + Serializer = new BinaryReflectiveSerializer {RawMode = raw} + } + } + }); CheckObject(marsh, new OuterObjectType(), new InnerObjectType()); } [Test] - public void TestStructsReflective() + public void TestStructsReflective([Values(false, true)] bool raw) { var marsh = new Marshaller(new BinaryConfiguration { - TypeConfigurations = new[] {new BinaryTypeConfiguration(typeof (ReflectiveStruct))} + TypeConfigurations = + new[] + { + new BinaryTypeConfiguration(typeof (ReflectiveStruct)) + { + Serializer = new BinaryReflectiveSerializer {RawMode = raw} + } + } }); var obj = new ReflectiveStruct(15, 28.8); http://git-wip-us.apache.org/repos/asf/ignite/blob/cba4f4c0/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj b/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj index 1b66f0c..6acc7c4 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj @@ -65,6 +65,7 @@ <Reference Include="System.Xml" /> </ItemGroup> <ItemGroup> + <Compile Include="Binary\BinaryReflectiveSerializer.cs" /> <Compile Include="Binary\Package-Info.cs" /> <Compile Include="Cache\CacheAtomicUpdateTimeoutException.cs" /> <Compile Include="Cache\CacheEntryProcessorException.cs" /> @@ -328,7 +329,6 @@ <Compile Include="Impl\Binary\BinaryReaderHandleDictionary.cs" /> <Compile Include="Impl\Binary\BinaryReader.cs" /> <Compile Include="Impl\Binary\BinaryReflectiveActions.cs" /> - <Compile Include="Impl\Binary\BinaryReflectiveSerializer.cs" /> <Compile Include="Impl\Binary\Binary.cs" /> <Compile Include="Impl\Binary\Structure\BinaryStructureTracker.cs" /> <Compile Include="Impl\Binary\BinarySurrogateTypeDescriptor.cs" /> http://git-wip-us.apache.org/repos/asf/ignite/blob/cba4f4c0/modules/platforms/dotnet/Apache.Ignite.Core/Binary/BinaryReflectiveSerializer.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Binary/BinaryReflectiveSerializer.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Binary/BinaryReflectiveSerializer.cs new file mode 100644 index 0000000..02703be --- /dev/null +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Binary/BinaryReflectiveSerializer.cs @@ -0,0 +1,241 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace Apache.Ignite.Core.Binary +{ + using System; + using System.Collections.Generic; + using System.Reflection; + using Apache.Ignite.Core.Impl.Binary; + + /// <summary> + /// Binary serializer which reflectively writes all fields except of ones with + /// <see cref="System.NonSerializedAttribute"/>. + /// <para /> + /// Note that Java platform stores dates as a difference between current time + /// and predefined absolute UTC date. Therefore, this difference is always the + /// same for all time zones. .NET, in contrast, stores dates as a difference + /// between current time and some predefined date relative to the current time + /// zone. It means that this difference will be different as you change time zones. + /// To overcome this discrepancy Ignite always converts .Net date to UTC form + /// before serializing and allows user to decide whether to deserialize them + /// in UTC or local form using <c>ReadTimestamp(..., true/false)</c> methods in + /// <see cref="IBinaryReader"/> and <see cref="IBinaryRawReader"/>. + /// This serializer always read dates in UTC form. It means that if you have + /// local date in any field/property, it will be implicitly converted to UTC + /// form after the first serialization-deserialization cycle. + /// </summary> + public sealed class BinaryReflectiveSerializer : IBinarySerializer + { + /** Cached binding flags. */ + private const BindingFlags Flags = BindingFlags.Instance | BindingFlags.Public | + BindingFlags.NonPublic | BindingFlags.DeclaredOnly; + + /** Cached type descriptors. */ + private readonly IDictionary<Type, Descriptor> _types = new Dictionary<Type, Descriptor>(); + + /** Raw mode flag. */ + private bool _rawMode; + + /// <summary> + /// Gets or value indicating whether raw mode serialization should be used. + /// <para /> + /// Raw mode does not include field names, improving performance and memory usage. + /// However, queries do not support raw objects. + /// </summary> + public bool RawMode + { + get { return _rawMode; } + set + { + if (_types.Count > 0) + throw new InvalidOperationException(typeof (BinarizableSerializer).Name + + ".RawMode cannot be changed after first serialization."); + + _rawMode = value; + } + } + + /// <summary> + /// Write portalbe object. + /// </summary> + /// <param name="obj">Object.</param> + /// <param name="writer">Writer.</param> + /// <exception cref="BinaryObjectException">Type is not registered in serializer: + type.Name</exception> + public void WriteBinary(object obj, IBinaryWriter writer) + { + var binarizable = obj as IBinarizable; + + if (binarizable != null) + binarizable.WriteBinary(writer); + else + GetDescriptor(obj).Write(obj, writer); + } + + /// <summary> + /// Read binary object. + /// </summary> + /// <param name="obj">Instantiated empty object.</param> + /// <param name="reader">Reader.</param> + /// <exception cref="BinaryObjectException">Type is not registered in serializer: + type.Name</exception> + public void ReadBinary(object obj, IBinaryReader reader) + { + var binarizable = obj as IBinarizable; + + if (binarizable != null) + binarizable.ReadBinary(reader); + else + GetDescriptor(obj).Read(obj, reader); + } + + /// <summary>Register type.</summary> + /// <param name="type">Type.</param> + /// <param name="typeId">Type ID.</param> + /// <param name="converter">Name converter.</param> + /// <param name="idMapper">ID mapper.</param> + internal void Register(Type type, int typeId, IBinaryNameMapper converter, + IBinaryIdMapper idMapper) + { + if (type.GetInterface(typeof(IBinarizable).Name) != null) + return; + + List<FieldInfo> fields = new List<FieldInfo>(); + + Type curType = type; + + while (curType != null) + { + foreach (FieldInfo field in curType.GetFields(Flags)) + { + if (!field.IsNotSerialized) + fields.Add(field); + } + + curType = curType.BaseType; + } + + IDictionary<int, string> idMap = new Dictionary<int, string>(); + + foreach (FieldInfo field in fields) + { + string fieldName = BinaryUtils.CleanFieldName(field.Name); + + int fieldId = BinaryUtils.FieldId(typeId, fieldName, converter, idMapper); + + if (idMap.ContainsKey(fieldId)) + { + throw new BinaryObjectException("Conflicting field IDs [type=" + + type.Name + ", field1=" + idMap[fieldId] + ", field2=" + fieldName + + ", fieldId=" + fieldId + ']'); + } + + idMap[fieldId] = fieldName; + } + + fields.Sort(Compare); + + Descriptor desc = new Descriptor(fields, _rawMode); + + _types[type] = desc; + } + + /// <summary> + /// Gets the descriptor for an object. + /// </summary> + private Descriptor GetDescriptor(object obj) + { + var type = obj.GetType(); + + Descriptor desc; + + if (!_types.TryGetValue(type, out desc)) + throw new BinaryObjectException("Type is not registered in serializer: " + type.Name); + + return desc; + } + + /// <summary> + /// Compare two FieldInfo instances. + /// </summary> + private static int Compare(FieldInfo info1, FieldInfo info2) { + string name1 = BinaryUtils.CleanFieldName(info1.Name); + string name2 = BinaryUtils.CleanFieldName(info2.Name); + + return string.Compare(name1, name2, StringComparison.OrdinalIgnoreCase); + } + + /// <summary> + /// Type descriptor. + /// </summary> + private class Descriptor + { + /** Write actions to be performed. */ + private readonly List<BinaryReflectiveWriteAction> _wActions; + + /** Read actions to be performed. */ + private readonly List<BinaryReflectiveReadAction> _rActions; + + /// <summary> + /// Constructor. + /// </summary> + /// <param name="fields">Fields.</param> + /// <param name="raw">Raw mode.</param> + public Descriptor(List<FieldInfo> fields, bool raw) + { + _wActions = new List<BinaryReflectiveWriteAction>(fields.Count); + _rActions = new List<BinaryReflectiveReadAction>(fields.Count); + + foreach (FieldInfo field in fields) + { + BinaryReflectiveWriteAction writeAction; + BinaryReflectiveReadAction readAction; + + BinaryReflectiveActions.GetTypeActions(field, out writeAction, out readAction, raw); + + _wActions.Add(writeAction); + _rActions.Add(readAction); + } + } + + /// <summary> + /// Write object. + /// </summary> + /// <param name="obj">Object.</param> + /// <param name="writer">Writer.</param> + public void Write(object obj, IBinaryWriter writer) + { + int cnt = _wActions.Count; + + for (int i = 0; i < cnt; i++) + _wActions[i](obj, writer); + } + + /// <summary> + /// Read object. + /// </summary> + /// <param name="obj">Object.</param> + /// <param name="reader">Reader.</param> + public void Read(object obj, IBinaryReader reader) + { + int cnt = _rActions.Count; + + for (int i = 0; i < cnt; i++ ) + _rActions[i](obj, reader); + } + } + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/cba4f4c0/modules/platforms/dotnet/Apache.Ignite.Core/Discovery/Tcp/Multicast/TcpDiscoveryMulticastIpFinder.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Discovery/Tcp/Multicast/TcpDiscoveryMulticastIpFinder.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Discovery/Tcp/Multicast/TcpDiscoveryMulticastIpFinder.cs index 5df5ea1..4581a04 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Discovery/Tcp/Multicast/TcpDiscoveryMulticastIpFinder.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Discovery/Tcp/Multicast/TcpDiscoveryMulticastIpFinder.cs @@ -91,7 +91,7 @@ namespace Apache.Ignite.Core.Discovery.Tcp.Multicast /// Gets or sets the time to live for multicast packets sent out on this /// IP finder in order to control the scope of the multicast. /// </summary> - public byte? TimeToLive { get; set; } // TODO: Nullable? + public byte? TimeToLive { get; set; } /// <summary> /// Initializes a new instance of the <see cref="TcpDiscoveryMulticastIpFinder"/> class. http://git-wip-us.apache.org/repos/asf/ignite/blob/cba4f4c0/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReflectiveActions.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReflectiveActions.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReflectiveActions.cs index 15509fc..8b5e2a1 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReflectiveActions.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReflectiveActions.cs @@ -49,29 +49,53 @@ namespace Apache.Ignite.Core.Impl.Binary private static readonly MethodInfo MthdReadEnum = typeof(IBinaryReader).GetMethod("ReadEnum", new[] { typeof(string) }); + /** Method: read enum. */ + private static readonly MethodInfo MthdReadEnumRaw = typeof (IBinaryRawReader).GetMethod("ReadEnum"); + /** Method: read enum array. */ private static readonly MethodInfo MthdReadEnumArray = typeof(IBinaryReader).GetMethod("ReadEnumArray", new[] { typeof(string) }); + /** Method: read enum array. */ + private static readonly MethodInfo MthdReadEnumArrayRaw = typeof(IBinaryRawReader).GetMethod("ReadEnumArray"); + /** Method: read array. */ private static readonly MethodInfo MthdReadObjArray = typeof(IBinaryReader).GetMethod("ReadArray", new[] { typeof(string) }); + /** Method: read array. */ + private static readonly MethodInfo MthdReadObjArrayRaw = typeof(IBinaryRawReader).GetMethod("ReadArray"); + /** Method: read object. */ private static readonly MethodInfo MthdReadObj= typeof(IBinaryReader).GetMethod("ReadObject", new[] { typeof(string) }); + /** Method: read object. */ + private static readonly MethodInfo MthdReadObjRaw = typeof(IBinaryRawReader).GetMethod("ReadObject"); + /** Method: write enum array. */ - private static readonly MethodInfo MthdWriteEnumArray = - typeof(IBinaryWriter).GetMethod("WriteEnumArray"); + private static readonly MethodInfo MthdWriteEnumArray = typeof(IBinaryWriter).GetMethod("WriteEnumArray"); + + /** Method: write enum array. */ + private static readonly MethodInfo MthdWriteEnumArrayRaw = typeof(IBinaryRawWriter).GetMethod("WriteEnumArray"); /** Method: write array. */ - private static readonly MethodInfo MthdWriteObjArray = - typeof(IBinaryWriter).GetMethod("WriteArray"); + private static readonly MethodInfo MthdWriteObjArray = typeof(IBinaryWriter).GetMethod("WriteArray"); - /** Method: read object. */ - private static readonly MethodInfo MthdWriteObj = - typeof(IBinaryWriter).GetMethod("WriteObject"); + /** Method: write array. */ + private static readonly MethodInfo MthdWriteObjArrayRaw = typeof(IBinaryRawWriter).GetMethod("WriteArray"); + + /** Method: write object. */ + private static readonly MethodInfo MthdWriteObj = typeof(IBinaryWriter).GetMethod("WriteObject"); + + /** Method: write object. */ + private static readonly MethodInfo MthdWriteObjRaw = typeof(IBinaryRawWriter).GetMethod("WriteObject"); + + /** Method: raw writer */ + private static readonly MethodInfo MthdGetRawWriter = typeof(IBinaryWriter).GetMethod("GetRawWriter"); + + /** Method: raw writer */ + private static readonly MethodInfo MthdGetRawReader = typeof(IBinaryReader).GetMethod("GetRawReader"); /// <summary> /// Lookup read/write actions for the given type. @@ -79,17 +103,18 @@ namespace Apache.Ignite.Core.Impl.Binary /// <param name="field">The field.</param> /// <param name="writeAction">Write action.</param> /// <param name="readAction">Read action.</param> - public static void TypeActions(FieldInfo field, out BinaryReflectiveWriteAction writeAction, - out BinaryReflectiveReadAction readAction) + /// <param name="raw">Raw mode.</param> + public static void GetTypeActions(FieldInfo field, out BinaryReflectiveWriteAction writeAction, + out BinaryReflectiveReadAction readAction, bool raw) { var type = field.FieldType; if (type.IsPrimitive) - HandlePrimitive(field, out writeAction, out readAction); + HandlePrimitive(field, out writeAction, out readAction, raw); else if (type.IsArray) - HandleArray(field, out writeAction, out readAction); + HandleArray(field, out writeAction, out readAction, raw); else - HandleOther(field, out writeAction, out readAction); + HandleOther(field, out writeAction, out readAction, raw); } /// <summary> @@ -98,71 +123,108 @@ namespace Apache.Ignite.Core.Impl.Binary /// <param name="field">The field.</param> /// <param name="writeAction">Write action.</param> /// <param name="readAction">Read action.</param> + /// <param name="raw">Raw mode.</param> /// <exception cref="IgniteException">Unsupported primitive type: + type.Name</exception> private static void HandlePrimitive(FieldInfo field, out BinaryReflectiveWriteAction writeAction, - out BinaryReflectiveReadAction readAction) + out BinaryReflectiveReadAction readAction, bool raw) { var type = field.FieldType; - if (type == typeof(bool)) + if (type == typeof (bool)) { - writeAction = GetWriter<bool>(field, (f, w, o) => w.WriteBoolean(f, o)); - readAction = GetReader(field, (f, r) => r.ReadBoolean(f)); + writeAction = raw + ? GetRawWriter<bool>(field, (w, o) => w.WriteBoolean(o)) + : GetWriter<bool>(field, (f, w, o) => w.WriteBoolean(f, o)); + readAction = raw + ? GetRawReader(field, r => r.ReadBoolean()) + : GetReader(field, (f, r) => r.ReadBoolean(f)); } - else if (type == typeof(sbyte)) + else if (type == typeof (sbyte)) { - writeAction = GetWriter<sbyte>(field, (f, w, o) => w.WriteByte(f, unchecked((byte) o))); - readAction = GetReader(field, (f, r) => unchecked ((sbyte)r.ReadByte(f))); + writeAction = raw + ? GetRawWriter<sbyte>(field, (w, o) => w.WriteByte(unchecked((byte) o))) + : GetWriter<sbyte>(field, (f, w, o) => w.WriteByte(f, unchecked((byte) o))); + readAction = raw + ? GetRawReader(field, r => unchecked ((sbyte) r.ReadByte())) + : GetReader(field, (f, r) => unchecked ((sbyte) r.ReadByte(f))); } - else if (type == typeof(byte)) + else if (type == typeof (byte)) { - writeAction = GetWriter<byte>(field, (f, w, o) => w.WriteByte(f, o)); - readAction = GetReader(field, (f, r) => r.ReadByte(f)); + writeAction = raw + ? GetRawWriter<byte>(field, (w, o) => w.WriteByte(o)) + : GetWriter<byte>(field, (f, w, o) => w.WriteByte(f, o)); + readAction = raw ? GetRawReader(field, r => r.ReadByte()) : GetReader(field, (f, r) => r.ReadByte(f)); } - else if (type == typeof(short)) + else if (type == typeof (short)) { - writeAction = GetWriter<short>(field, (f, w, o) => w.WriteShort(f, o)); - readAction = GetReader(field, (f, r) => r.ReadShort(f)); + writeAction = raw + ? GetRawWriter<short>(field, (w, o) => w.WriteShort(o)) + : GetWriter<short>(field, (f, w, o) => w.WriteShort(f, o)); + readAction = raw ? GetRawReader(field, r => r.ReadShort()) : GetReader(field, (f, r) => r.ReadShort(f)); } - else if (type == typeof(ushort)) + else if (type == typeof (ushort)) { - writeAction = GetWriter<ushort>(field, (f, w, o) => w.WriteShort(f, unchecked((short) o))); - readAction = GetReader(field, (f, r) => unchecked((ushort) r.ReadShort(f))); + writeAction = raw + ? GetRawWriter<ushort>(field, (w, o) => w.WriteShort(unchecked((short) o))) + : GetWriter<ushort>(field, (f, w, o) => w.WriteShort(f, unchecked((short) o))); + readAction = raw + ? GetRawReader(field, r => unchecked((ushort) r.ReadShort())) + : GetReader(field, (f, r) => unchecked((ushort) r.ReadShort(f))); } - else if (type == typeof(char)) + else if (type == typeof (char)) { - writeAction = GetWriter<char>(field, (f, w, o) => w.WriteChar(f, o)); - readAction = GetReader(field, (f, r) => r.ReadChar(f)); + writeAction = raw + ? GetRawWriter<char>(field, (w, o) => w.WriteChar(o)) + : GetWriter<char>(field, (f, w, o) => w.WriteChar(f, o)); + readAction = raw ? GetRawReader(field, r => r.ReadChar()) : GetReader(field, (f, r) => r.ReadChar(f)); } - else if (type == typeof(int)) + else if (type == typeof (int)) { - writeAction = GetWriter<int>(field, (f, w, o) => w.WriteInt(f, o)); - readAction = GetReader(field, (f, r) => r.ReadInt(f)); + writeAction = raw + ? GetRawWriter<int>(field, (w, o) => w.WriteInt(o)) + : GetWriter<int>(field, (f, w, o) => w.WriteInt(f, o)); + readAction = raw ? GetRawReader(field, r => r.ReadInt()) : GetReader(field, (f, r) => r.ReadInt(f)); } - else if (type == typeof(uint)) + else if (type == typeof (uint)) { - writeAction = GetWriter<uint>(field, (f, w, o) => w.WriteInt(f, unchecked((int) o))); - readAction = GetReader(field, (f, r) => unchecked((uint) r.ReadInt(f))); + writeAction = raw + ? GetRawWriter<uint>(field, (w, o) => w.WriteInt(unchecked((int) o))) + : GetWriter<uint>(field, (f, w, o) => w.WriteInt(f, unchecked((int) o))); + readAction = raw + ? GetRawReader(field, r => unchecked((uint) r.ReadInt())) + : GetReader(field, (f, r) => unchecked((uint) r.ReadInt(f))); } - else if (type == typeof(long)) + else if (type == typeof (long)) { - writeAction = GetWriter<long>(field, (f, w, o) => w.WriteLong(f, o)); - readAction = GetReader(field, (f, r) => r.ReadLong(f)); + writeAction = raw + ? GetRawWriter<long>(field, (w, o) => w.WriteLong(o)) + : GetWriter<long>(field, (f, w, o) => w.WriteLong(f, o)); + readAction = raw ? GetRawReader(field, r => r.ReadLong()) : GetReader(field, (f, r) => r.ReadLong(f)); } - else if (type == typeof(ulong)) + else if (type == typeof (ulong)) { - writeAction = GetWriter<ulong>(field, (f, w, o) => w.WriteLong(f, unchecked((long) o))); - readAction = GetReader(field, (f, r) => unchecked((ulong) r.ReadLong(f))); + writeAction = raw + ? GetRawWriter<ulong>(field, (w, o) => w.WriteLong(unchecked((long) o))) + : GetWriter<ulong>(field, (f, w, o) => w.WriteLong(f, unchecked((long) o))); + readAction = raw + ? GetRawReader(field, r => unchecked((ulong) r.ReadLong())) + : GetReader(field, (f, r) => unchecked((ulong) r.ReadLong(f))); } - else if (type == typeof(float)) + else if (type == typeof (float)) { - writeAction = GetWriter<float>(field, (f, w, o) => w.WriteFloat(f, o)); - readAction = GetReader(field, (f, r) => r.ReadFloat(f)); + writeAction = raw + ? GetRawWriter<float>(field, (w, o) => w.WriteFloat(o)) + : GetWriter<float>(field, (f, w, o) => w.WriteFloat(f, o)); + readAction = raw ? GetRawReader(field, r => r.ReadFloat()) : GetReader(field, (f, r) => r.ReadFloat(f)); } - else if (type == typeof(double)) + else if (type == typeof (double)) { - writeAction = GetWriter<double>(field, (f, w, o) => w.WriteDouble(f, o)); - readAction = GetReader(field, (f, r) => r.ReadDouble(f)); + writeAction = raw + ? GetRawWriter<double>(field, (w, o) => w.WriteDouble(o)) + : GetWriter<double>(field, (f, w, o) => w.WriteDouble(f, o)); + readAction = raw + ? GetRawReader(field, r => r.ReadDouble()) + : GetReader(field, (f, r) => r.ReadDouble(f)); } else throw new IgniteException("Unsupported primitive type: " + type.Name); @@ -174,96 +236,165 @@ namespace Apache.Ignite.Core.Impl.Binary /// <param name="field">The field.</param> /// <param name="writeAction">Write action.</param> /// <param name="readAction">Read action.</param> + /// <param name="raw">Raw mode.</param> private static void HandleArray(FieldInfo field, out BinaryReflectiveWriteAction writeAction, - out BinaryReflectiveReadAction readAction) + out BinaryReflectiveReadAction readAction, bool raw) { Type elemType = field.FieldType.GetElementType(); - if (elemType == typeof(bool)) - { - writeAction = GetWriter<bool[]>(field, (f, w, o) => w.WriteBooleanArray(f, o)); - readAction = GetReader(field, (f, r) => r.ReadBooleanArray(f)); - } - else if (elemType == typeof(byte)) - { - writeAction = GetWriter<byte[]>(field, (f, w, o) => w.WriteByteArray(f, o)); - readAction = GetReader(field, (f, r) => r.ReadByteArray(f)); - } - else if (elemType == typeof(sbyte)) - { - writeAction = GetWriter<sbyte[]>(field, (f, w, o) => w.WriteByteArray(f, (byte[]) (Array) o)); - readAction = GetReader(field, (f, r) => (sbyte[]) (Array) r.ReadByteArray(f)); - } - else if (elemType == typeof(short)) - { - writeAction = GetWriter<short[]>(field, (f, w, o) => w.WriteShortArray(f, o)); - readAction = GetReader(field, (f, r) => r.ReadShortArray(f)); - } - else if (elemType == typeof(ushort)) - { - writeAction = GetWriter<ushort[]>(field, (f, w, o) => w.WriteShortArray(f, (short[]) (Array) o)); - readAction = GetReader(field, (f, r) => (ushort[]) (Array) r.ReadShortArray(f)); - } - else if (elemType == typeof(char)) - { - writeAction = GetWriter<char[]>(field, (f, w, o) => w.WriteCharArray(f, o)); - readAction = GetReader(field, (f, r) => r.ReadCharArray(f)); - } - else if (elemType == typeof(int)) - { - writeAction = GetWriter<int[]>(field, (f, w, o) => w.WriteIntArray(f, o)); - readAction = GetReader(field, (f, r) => r.ReadIntArray(f)); - } - else if (elemType == typeof(uint)) - { - writeAction = GetWriter<uint[]>(field, (f, w, o) => w.WriteIntArray(f, (int[]) (Array) o)); - readAction = GetReader(field, (f, r) => (uint[]) (Array) r.ReadIntArray(f)); + if (elemType == typeof (bool)) + { + writeAction = raw + ? GetRawWriter<bool[]>(field, (w, o) => w.WriteBooleanArray(o)) + : GetWriter<bool[]>(field, (f, w, o) => w.WriteBooleanArray(f, o)); + readAction = raw + ? GetRawReader(field, r => r.ReadBooleanArray()) + : GetReader(field, (f, r) => r.ReadBooleanArray(f)); + } + else if (elemType == typeof (byte)) + { + writeAction = raw + ? GetRawWriter<byte[]>(field, (w, o) => w.WriteByteArray(o)) + : GetWriter<byte[]>(field, (f, w, o) => w.WriteByteArray(f, o)); + readAction = raw + ? GetRawReader(field, r => r.ReadByteArray()) + : GetReader(field, (f, r) => r.ReadByteArray(f)); + } + else if (elemType == typeof (sbyte)) + { + writeAction = raw + ? GetRawWriter<sbyte[]>(field, (w, o) => w.WriteByteArray((byte[]) (Array) o)) + : GetWriter<sbyte[]>(field, (f, w, o) => w.WriteByteArray(f, (byte[]) (Array) o)); + readAction = raw + ? GetRawReader(field, r => (sbyte[]) (Array) r.ReadByteArray()) + : GetReader(field, (f, r) => (sbyte[]) (Array) r.ReadByteArray(f)); + } + else if (elemType == typeof (short)) + { + writeAction = raw + ? GetRawWriter<short[]>(field, (w, o) => w.WriteShortArray(o)) + : GetWriter<short[]>(field, (f, w, o) => w.WriteShortArray(f, o)); + readAction = raw + ? GetRawReader(field, r => r.ReadShortArray()) + : GetReader(field, (f, r) => r.ReadShortArray(f)); + } + else if (elemType == typeof (ushort)) + { + writeAction = raw + ? GetRawWriter<ushort[]>(field, (w, o) => w.WriteShortArray((short[]) (Array) o)) + : GetWriter<ushort[]>(field, (f, w, o) => w.WriteShortArray(f, (short[]) (Array) o)); + readAction = raw + ? GetRawReader(field, r => (ushort[]) (Array) r.ReadShortArray()) + : GetReader(field, (f, r) => (ushort[]) (Array) r.ReadShortArray(f)); + } + else if (elemType == typeof (char)) + { + writeAction = raw + ? GetRawWriter<char[]>(field, (w, o) => w.WriteCharArray(o)) + : GetWriter<char[]>(field, (f, w, o) => w.WriteCharArray(f, o)); + readAction = raw + ? GetRawReader(field, r => r.ReadCharArray()) + : GetReader(field, (f, r) => r.ReadCharArray(f)); + } + else if (elemType == typeof (int)) + { + writeAction = raw + ? GetRawWriter<int[]>(field, (w, o) => w.WriteIntArray(o)) + : GetWriter<int[]>(field, (f, w, o) => w.WriteIntArray(f, o)); + readAction = raw + ? GetRawReader(field, r => r.ReadIntArray()) + : GetReader(field, (f, r) => r.ReadIntArray(f)); + } + else if (elemType == typeof (uint)) + { + writeAction = raw + ? GetRawWriter<uint[]>(field, (w, o) => w.WriteIntArray((int[]) (Array) o)) + : GetWriter<uint[]>(field, (f, w, o) => w.WriteIntArray(f, (int[]) (Array) o)); + readAction = raw + ? GetRawReader(field, r => (uint[]) (Array) r.ReadIntArray()) + : GetReader(field, (f, r) => (uint[]) (Array) r.ReadIntArray(f)); + } + else if (elemType == typeof (long)) + { + writeAction = raw + ? GetRawWriter<long[]>(field, (w, o) => w.WriteLongArray(o)) + : GetWriter<long[]>(field, (f, w, o) => w.WriteLongArray(f, o)); + readAction = raw + ? GetRawReader(field, r => r.ReadLongArray()) + : GetReader(field, (f, r) => r.ReadLongArray(f)); + } + else if (elemType == typeof (ulong)) + { + writeAction = raw + ? GetRawWriter<ulong[]>(field, (w, o) => w.WriteLongArray((long[]) (Array) o)) + : GetWriter<ulong[]>(field, (f, w, o) => w.WriteLongArray(f, (long[]) (Array) o)); + readAction = raw + ? GetRawReader(field, r => (ulong[]) (Array) r.ReadLongArray()) + : GetReader(field, (f, r) => (ulong[]) (Array) r.ReadLongArray(f)); + } + else if (elemType == typeof (float)) + { + writeAction = raw + ? GetRawWriter<float[]>(field, (w, o) => w.WriteFloatArray(o)) + : GetWriter<float[]>(field, (f, w, o) => w.WriteFloatArray(f, o)); + readAction = raw + ? GetRawReader(field, r => r.ReadFloatArray()) + : GetReader(field, (f, r) => r.ReadFloatArray(f)); + } + else if (elemType == typeof (double)) + { + writeAction = raw + ? GetRawWriter<double[]>(field, (w, o) => w.WriteDoubleArray(o)) + : GetWriter<double[]>(field, (f, w, o) => w.WriteDoubleArray(f, o)); + readAction = raw + ? GetRawReader(field, r => r.ReadDoubleArray()) + : GetReader(field, (f, r) => r.ReadDoubleArray(f)); + } + else if (elemType == typeof (decimal?)) + { + writeAction = raw + ? GetRawWriter<decimal?[]>(field, (w, o) => w.WriteDecimalArray(o)) + : GetWriter<decimal?[]>(field, (f, w, o) => w.WriteDecimalArray(f, o)); + readAction = raw + ? GetRawReader(field, r => r.ReadDecimalArray()) + : GetReader(field, (f, r) => r.ReadDecimalArray(f)); + } + else if (elemType == typeof (string)) + { + writeAction = raw + ? GetRawWriter<string[]>(field, (w, o) => w.WriteStringArray(o)) + : GetWriter<string[]>(field, (f, w, o) => w.WriteStringArray(f, o)); + readAction = raw + ? GetRawReader(field, r => r.ReadStringArray()) + : GetReader(field, (f, r) => r.ReadStringArray(f)); + } + else if (elemType == typeof (Guid?)) + { + writeAction = raw + ? GetRawWriter<Guid?[]>(field, (w, o) => w.WriteGuidArray(o)) + : GetWriter<Guid?[]>(field, (f, w, o) => w.WriteGuidArray(f, o)); + readAction = raw + ? GetRawReader(field, r => r.ReadGuidArray()) + : GetReader(field, (f, r) => r.ReadGuidArray(f)); } - else if (elemType == typeof(long)) - { - writeAction = GetWriter<long[]>(field, (f, w, o) => w.WriteLongArray(f, o)); - readAction = GetReader(field, (f, r) => r.ReadLongArray(f)); - } - else if (elemType == typeof(ulong)) - { - writeAction = GetWriter<ulong[]>(field, (f, w, o) => w.WriteLongArray(f, (long[]) (Array) o)); - readAction = GetReader(field, (f, r) => (ulong[]) (Array) r.ReadLongArray(f)); - } - else if (elemType == typeof(float)) - { - writeAction = GetWriter<float[]>(field, (f, w, o) => w.WriteFloatArray(f, o)); - readAction = GetReader(field, (f, r) => r.ReadFloatArray(f)); - } - else if (elemType == typeof(double)) - { - writeAction = GetWriter<double[]>(field, (f, w, o) => w.WriteDoubleArray(f, o)); - readAction = GetReader(field, (f, r) => r.ReadDoubleArray(f)); - } - else if (elemType == typeof(decimal?)) - { - writeAction = GetWriter<decimal?[]>(field, (f, w, o) => w.WriteDecimalArray(f, o)); - readAction = GetReader(field, (f, r) => r.ReadDecimalArray(f)); - } - else if (elemType == typeof(string)) - { - writeAction = GetWriter<string[]>(field, (f, w, o) => w.WriteStringArray(f, o)); - readAction = GetReader(field, (f, r) => r.ReadStringArray(f)); - } - else if (elemType == typeof(Guid?)) - { - writeAction = GetWriter<Guid?[]>(field, (f, w, o) => w.WriteGuidArray(f, o)); - readAction = GetReader(field, (f, r) => r.ReadGuidArray(f)); - } else if (elemType.IsEnum) { - writeAction = GetWriter(field, MthdWriteEnumArray, elemType); - readAction = GetReader(field, MthdReadEnumArray, elemType); + writeAction = raw + ? GetRawWriter(field, MthdWriteEnumArrayRaw, elemType) + : GetWriter(field, MthdWriteEnumArray, elemType); + readAction = raw + ? GetRawReader(field, MthdReadEnumArrayRaw, elemType) + : GetReader(field, MthdReadEnumArray, elemType); } else { - writeAction = GetWriter(field, MthdWriteObjArray, elemType); - readAction = GetReader(field, MthdReadObjArray, elemType); - } + writeAction = raw + ? GetRawWriter(field, MthdWriteObjArrayRaw, elemType) + : GetWriter(field, MthdWriteObjArray, elemType); + readAction = raw + ? GetRawReader(field, MthdReadObjArrayRaw, elemType) + : GetReader(field, MthdReadObjArray, elemType); + } } /// <summary> @@ -272,57 +403,84 @@ namespace Apache.Ignite.Core.Impl.Binary /// <param name="field">The field.</param> /// <param name="writeAction">Write action.</param> /// <param name="readAction">Read action.</param> + /// <param name="raw">Raw mode.</param> private static void HandleOther(FieldInfo field, out BinaryReflectiveWriteAction writeAction, - out BinaryReflectiveReadAction readAction) + out BinaryReflectiveReadAction readAction, bool raw) { var type = field.FieldType; var genericDef = type.IsGenericType ? type.GetGenericTypeDefinition() : null; - bool nullable = genericDef == typeof(Nullable<>); + bool nullable = genericDef == typeof (Nullable<>); var nullableType = nullable ? type.GetGenericArguments()[0] : null; - if (type == typeof(decimal)) + if (type == typeof (decimal)) { - writeAction = GetWriter<decimal>(field, (f, w, o) => w.WriteDecimal(f, o)); - readAction = GetReader(field, (f, r) => r.ReadDecimal(f)); + writeAction = raw + ? GetRawWriter<decimal>(field, (w, o) => w.WriteDecimal(o)) + : GetWriter<decimal>(field, (f, w, o) => w.WriteDecimal(f, o)); + readAction = raw + ? GetRawReader(field, r => r.ReadDecimal()) + : GetReader(field, (f, r) => r.ReadDecimal(f)); } - else if (type == typeof(string)) + else if (type == typeof (string)) { - writeAction = GetWriter<string>(field, (f, w, o) => w.WriteString(f, o)); - readAction = GetReader(field, (f, r) => r.ReadString(f)); + writeAction = raw + ? GetRawWriter<string>(field, (w, o) => w.WriteString(o)) + : GetWriter<string>(field, (f, w, o) => w.WriteString(f, o)); + readAction = raw + ? GetRawReader(field, r => r.ReadString()) + : GetReader(field, (f, r) => r.ReadString(f)); } - else if (type == typeof(Guid)) + else if (type == typeof (Guid)) { - writeAction = GetWriter<Guid>(field, (f, w, o) => w.WriteGuid(f, o)); - readAction = GetReader(field, (f, r) => r.ReadObject<Guid>(f)); + writeAction = raw + ? GetRawWriter<Guid>(field, (w, o) => w.WriteGuid(o)) + : GetWriter<Guid>(field, (f, w, o) => w.WriteGuid(f, o)); + readAction = raw + ? GetRawReader(field, r => r.ReadObject<Guid>()) + : GetReader(field, (f, r) => r.ReadObject<Guid>(f)); } - else if (nullable && nullableType == typeof(Guid)) + else if (nullable && nullableType == typeof (Guid)) { - writeAction = GetWriter<Guid?>(field, (f, w, o) => w.WriteGuid(f, o)); - readAction = GetReader(field, (f, r) => r.ReadGuid(f)); - } + writeAction = raw + ? GetRawWriter<Guid?>(field, (w, o) => w.WriteGuid(o)) + : GetWriter<Guid?>(field, (f, w, o) => w.WriteGuid(f, o)); + readAction = raw ? GetRawReader(field, r => r.ReadGuid()) : GetReader(field, (f, r) => r.ReadGuid(f)); + } else if (type.IsEnum) { - writeAction = GetWriter<object>(field, (f, w, o) => w.WriteEnum(f, o), true); - readAction = GetReader(field, MthdReadEnum); + writeAction = raw + ? GetRawWriter<object>(field, (w, o) => w.WriteEnum(o), true) + : GetWriter<object>(field, (f, w, o) => w.WriteEnum(f, o), true); + readAction = raw ? GetRawReader(field, MthdReadEnumRaw) : GetReader(field, MthdReadEnum); } - else if (type == BinaryUtils.TypDictionary || type.GetInterface(BinaryUtils.TypDictionary.FullName) != null && !type.IsGenericType) + else if (type == BinaryUtils.TypDictionary || + type.GetInterface(BinaryUtils.TypDictionary.FullName) != null && !type.IsGenericType) { - writeAction = GetWriter<IDictionary>(field, (f, w, o) => w.WriteDictionary(f, o)); - readAction = GetReader(field, (f, r) => r.ReadDictionary(f)); + writeAction = raw + ? GetRawWriter<IDictionary>(field, (w, o) => w.WriteDictionary(o)) + : GetWriter<IDictionary>(field, (f, w, o) => w.WriteDictionary(f, o)); + readAction = raw + ? GetRawReader(field, r => r.ReadDictionary()) + : GetReader(field, (f, r) => r.ReadDictionary(f)); } - else if (type == BinaryUtils.TypCollection || type.GetInterface(BinaryUtils.TypCollection.FullName) != null && !type.IsGenericType) + else if (type == BinaryUtils.TypCollection || + type.GetInterface(BinaryUtils.TypCollection.FullName) != null && !type.IsGenericType) { - writeAction = GetWriter<ICollection>(field, (f, w, o) => w.WriteCollection(f, o)); - readAction = GetReader(field, (f, r) => r.ReadCollection(f)); + writeAction = raw + ? GetRawWriter<ICollection>(field, (w, o) => w.WriteCollection(o)) + : GetWriter<ICollection>(field, (f, w, o) => w.WriteCollection(f, o)); + readAction = raw + ? GetRawReader(field, r => r.ReadCollection()) + : GetReader(field, (f, r) => r.ReadCollection(f)); } else { - writeAction = GetWriter(field, MthdWriteObj); - readAction = GetReader(field, MthdReadObj); - } + writeAction = raw ? GetRawWriter(field, MthdWriteObjRaw) : GetWriter(field, MthdWriteObj); + readAction = raw ? GetRawReader(field, MthdReadObjRaw) : GetReader(field, MthdReadObj); + } } /// <summary> @@ -334,6 +492,7 @@ namespace Apache.Ignite.Core.Impl.Binary { Debug.Assert(field != null); Debug.Assert(field.DeclaringType != null); // non-static + Debug.Assert(write != null); // Get field value var targetParam = Expression.Parameter(typeof(object)); @@ -353,13 +512,59 @@ namespace Apache.Ignite.Core.Impl.Binary } /// <summary> + /// Gets the reader with a specified write action. + /// </summary> + private static BinaryReflectiveWriteAction GetRawWriter<T>(FieldInfo field, + Expression<Action<IBinaryRawWriter, T>> write, + bool convertFieldValToObject = false) + { + Debug.Assert(field != null); + Debug.Assert(field.DeclaringType != null); // non-static + Debug.Assert(write != null); + + // Get field value + var targetParam = Expression.Parameter(typeof(object)); + var targetParamConverted = Expression.Convert(targetParam, field.DeclaringType); + Expression fldExpr = Expression.Field(targetParamConverted, field); + + if (convertFieldValToObject) + fldExpr = Expression.Convert(fldExpr, typeof (object)); + + // Call Writer method + var writerParam = Expression.Parameter(typeof(IBinaryWriter)); + var writeExpr = Expression.Invoke(write, Expression.Call(writerParam, MthdGetRawWriter), fldExpr); + + // Compile and return + return Expression.Lambda<BinaryReflectiveWriteAction>(writeExpr, targetParam, writerParam).Compile(); + } + + /// <summary> /// Gets the writer with a specified generic method. /// </summary> - private static BinaryReflectiveWriteAction GetWriter(FieldInfo field, MethodInfo method, + private static BinaryReflectiveWriteAction GetWriter(FieldInfo field, MethodInfo method, + params Type[] genericArgs) + { + return GetWriter0(field, method, false, genericArgs); + } + + /// <summary> + /// Gets the writer with a specified generic method. + /// </summary> + private static BinaryReflectiveWriteAction GetRawWriter(FieldInfo field, MethodInfo method, + params Type[] genericArgs) + { + return GetWriter0(field, method, true, genericArgs); + } + + /// <summary> + /// Gets the writer with a specified generic method. + /// </summary> + private static BinaryReflectiveWriteAction GetWriter0(FieldInfo field, MethodInfo method, bool raw, params Type[] genericArgs) { Debug.Assert(field != null); Debug.Assert(field.DeclaringType != null); // non-static + Debug.Assert(method != null); if (genericArgs.Length == 0) genericArgs = new[] {field.FieldType}; @@ -370,10 +575,14 @@ namespace Apache.Ignite.Core.Impl.Binary var fldExpr = Expression.Field(targetParamConverted, field); // Call Writer method - var writerParam = Expression.Parameter(typeof(IBinaryWriter)); - var fldNameParam = Expression.Constant(BinaryUtils.CleanFieldName(field.Name)); + var writerParam = Expression.Parameter(typeof (IBinaryWriter)); + var writeMethod = method.MakeGenericMethod(genericArgs); - var writeExpr = Expression.Call(writerParam, writeMethod, fldNameParam, fldExpr); + + var writeExpr = raw + ? Expression.Call(Expression.Call(writerParam, MthdGetRawWriter), writeMethod, fldExpr) + : Expression.Call(writerParam, writeMethod, Expression.Constant(BinaryUtils.CleanFieldName(field.Name)), + fldExpr); // Compile and return return Expression.Lambda<BinaryReflectiveWriteAction>(writeExpr, targetParam, writerParam).Compile(); @@ -405,9 +614,51 @@ namespace Apache.Ignite.Core.Impl.Binary } /// <summary> + /// Gets the reader with a specified read action. + /// </summary> + private static BinaryReflectiveReadAction GetRawReader<T>(FieldInfo field, + Expression<Func<IBinaryRawReader, T>> read) + { + Debug.Assert(field != null); + Debug.Assert(field.DeclaringType != null); // non-static + + // Call Reader method + var readerParam = Expression.Parameter(typeof(IBinaryReader)); + Expression readExpr = Expression.Invoke(read, Expression.Call(readerParam, MthdGetRawReader)); + + if (typeof(T) != field.FieldType) + readExpr = Expression.Convert(readExpr, field.FieldType); + + // Assign field value + var targetParam = Expression.Parameter(typeof(object)); + var assignExpr = Expression.Call(DelegateConverter.GetWriteFieldMethod(field), targetParam, readExpr); + + // Compile and return + return Expression.Lambda<BinaryReflectiveReadAction>(assignExpr, targetParam, readerParam).Compile(); + } + + /// <summary> /// Gets the reader with a specified generic method. /// </summary> - private static BinaryReflectiveReadAction GetReader(FieldInfo field, MethodInfo method, + private static BinaryReflectiveReadAction GetReader(FieldInfo field, MethodInfo method, + params Type[] genericArgs) + { + return GetReader0(field, method, false, genericArgs); + } + + /// <summary> + /// Gets the reader with a specified generic method. + /// </summary> + private static BinaryReflectiveReadAction GetRawReader(FieldInfo field, MethodInfo method, + params Type[] genericArgs) + { + return GetReader0(field, method, true, genericArgs); + } + + /// <summary> + /// Gets the reader with a specified generic method. + /// </summary> + private static BinaryReflectiveReadAction GetReader0(FieldInfo field, MethodInfo method, bool raw, params Type[] genericArgs) { Debug.Assert(field != null); @@ -418,9 +669,10 @@ namespace Apache.Ignite.Core.Impl.Binary // Call Reader method var readerParam = Expression.Parameter(typeof (IBinaryReader)); - var fldNameParam = Expression.Constant(BinaryUtils.CleanFieldName(field.Name)); var readMethod = method.MakeGenericMethod(genericArgs); - Expression readExpr = Expression.Call(readerParam, readMethod, fldNameParam); + Expression readExpr = raw + ? Expression.Call(Expression.Call(readerParam, MthdGetRawReader), readMethod) + : Expression.Call(readerParam, readMethod, Expression.Constant(BinaryUtils.CleanFieldName(field.Name))); if (readMethod.ReturnType != field.FieldType) readExpr = Expression.Convert(readExpr, field.FieldType); http://git-wip-us.apache.org/repos/asf/ignite/blob/cba4f4c0/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReflectiveSerializer.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReflectiveSerializer.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReflectiveSerializer.cs deleted file mode 100644 index ceffef5..0000000 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReflectiveSerializer.cs +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -namespace Apache.Ignite.Core.Impl.Binary -{ - using System; - using System.Collections.Generic; - using System.Reflection; - using Apache.Ignite.Core.Binary; - - /// <summary> - /// Binary serializer which reflectively writes all fields except of ones with - /// <see cref="System.NonSerializedAttribute"/>. - /// <para /> - /// Note that Java platform stores dates as a difference between current time - /// and predefined absolute UTC date. Therefore, this difference is always the - /// same for all time zones. .Net, in contrast, stores dates as a difference - /// between current time and some predefined date relative to the current time - /// zone. It means that this difference will be different as you change time zones. - /// To overcome this discrepancy Ignite always converts .Net date to UTC form - /// before serializing and allows user to decide whether to deserialize them - /// in UTC or local form using <c>ReadTimestamp(..., true/false)</c> methods in - /// <see cref="IBinaryReader"/> and <see cref="IBinaryRawReader"/>. - /// This serializer always read dates in UTC form. It means that if you have - /// local date in any field/property, it will be implicitly converted to UTC - /// form after the first serialization-deserialization cycle. - /// </summary> - internal class BinaryReflectiveSerializer : IBinarySerializer - { - /** Cached binding flags. */ - private const BindingFlags Flags = BindingFlags.Instance | BindingFlags.Public | - BindingFlags.NonPublic | BindingFlags.DeclaredOnly; - - /** Cached type descriptors. */ - private readonly IDictionary<Type, Descriptor> _types = new Dictionary<Type, Descriptor>(); - - /// <summary> - /// Write portalbe object. - /// </summary> - /// <param name="obj">Object.</param> - /// <param name="writer">Writer.</param> - /// <exception cref="BinaryObjectException">Type is not registered in serializer: + type.Name</exception> - public void WriteBinary(object obj, IBinaryWriter writer) - { - var binarizable = obj as IBinarizable; - - if (binarizable != null) - binarizable.WriteBinary(writer); - else - GetDescriptor(obj).Write(obj, writer); - } - - /// <summary> - /// Read binary object. - /// </summary> - /// <param name="obj">Instantiated empty object.</param> - /// <param name="reader">Reader.</param> - /// <exception cref="BinaryObjectException">Type is not registered in serializer: + type.Name</exception> - public void ReadBinary(object obj, IBinaryReader reader) - { - var binarizable = obj as IBinarizable; - - if (binarizable != null) - binarizable.ReadBinary(reader); - else - GetDescriptor(obj).Read(obj, reader); - } - - /// <summary>Register type.</summary> - /// <param name="type">Type.</param> - /// <param name="typeId">Type ID.</param> - /// <param name="converter">Name converter.</param> - /// <param name="idMapper">ID mapper.</param> - public void Register(Type type, int typeId, IBinaryNameMapper converter, - IBinaryIdMapper idMapper) - { - if (type.GetInterface(typeof(IBinarizable).Name) != null) - return; - - List<FieldInfo> fields = new List<FieldInfo>(); - - Type curType = type; - - while (curType != null) - { - foreach (FieldInfo field in curType.GetFields(Flags)) - { - if (!field.IsNotSerialized) - fields.Add(field); - } - - curType = curType.BaseType; - } - - IDictionary<int, string> idMap = new Dictionary<int, string>(); - - foreach (FieldInfo field in fields) - { - string fieldName = BinaryUtils.CleanFieldName(field.Name); - - int fieldId = BinaryUtils.FieldId(typeId, fieldName, converter, idMapper); - - if (idMap.ContainsKey(fieldId)) - { - throw new BinaryObjectException("Conflicting field IDs [type=" + - type.Name + ", field1=" + idMap[fieldId] + ", field2=" + fieldName + - ", fieldId=" + fieldId + ']'); - } - - idMap[fieldId] = fieldName; - } - - fields.Sort(Compare); - - Descriptor desc = new Descriptor(fields); - - _types[type] = desc; - } - - /// <summary> - /// Gets the descriptor for an object. - /// </summary> - private Descriptor GetDescriptor(object obj) - { - var type = obj.GetType(); - - Descriptor desc; - - if (!_types.TryGetValue(type, out desc)) - throw new BinaryObjectException("Type is not registered in serializer: " + type.Name); - - return desc; - } - - /// <summary> - /// Compare two FieldInfo instances. - /// </summary> - private static int Compare(FieldInfo info1, FieldInfo info2) { - string name1 = BinaryUtils.CleanFieldName(info1.Name); - string name2 = BinaryUtils.CleanFieldName(info2.Name); - - return string.Compare(name1, name2, StringComparison.OrdinalIgnoreCase); - } - - /// <summary> - /// Type descriptor. - /// </summary> - private class Descriptor - { - /** Write actions to be performed. */ - private readonly List<BinaryReflectiveWriteAction> _wActions; - - /** Read actions to be performed. */ - private readonly List<BinaryReflectiveReadAction> _rActions; - - /// <summary> - /// Constructor. - /// </summary> - /// <param name="fields">Fields.</param> - public Descriptor(List<FieldInfo> fields) - { - _wActions = new List<BinaryReflectiveWriteAction>(fields.Count); - _rActions = new List<BinaryReflectiveReadAction>(fields.Count); - - foreach (FieldInfo field in fields) - { - BinaryReflectiveWriteAction writeAction; - BinaryReflectiveReadAction readAction; - - BinaryReflectiveActions.TypeActions(field, out writeAction, out readAction); - - _wActions.Add(writeAction); - _rActions.Add(readAction); - } - } - - /// <summary> - /// Write object. - /// </summary> - /// <param name="obj">Object.</param> - /// <param name="writer">Writer.</param> - public void Write(object obj, IBinaryWriter writer) - { - int cnt = _wActions.Count; - - for (int i = 0; i < cnt; i++) - _wActions[i](obj, writer); - } - - /// <summary> - /// Read object. - /// </summary> - /// <param name="obj">Object.</param> - /// <param name="reader">Reader.</param> - public void Read(object obj, IBinaryReader reader) - { - int cnt = _rActions.Count; - - for (int i = 0; i < cnt; i++ ) - _rActions[i](obj, reader); - } - } - } -} http://git-wip-us.apache.org/repos/asf/ignite/blob/cba4f4c0/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryWriter.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryWriter.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryWriter.cs index a7ce544..5b1273e 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryWriter.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryWriter.cs @@ -950,10 +950,7 @@ namespace Apache.Ignite.Core.Impl.Binary { WriteFieldId(fieldName, BinaryUtils.TypeCollection); - if (val == null) - WriteNullField(); - else - WriteCollection(val); + WriteCollection(val); } /// <summary> @@ -962,8 +959,13 @@ namespace Apache.Ignite.Core.Impl.Binary /// <param name="val">Collection.</param> public void WriteCollection(ICollection val) { - WriteByte(BinaryUtils.TypeCollection); - BinaryUtils.WriteCollection(val, this); + if (val == null) + WriteNullField(); + else + { + WriteByte(BinaryUtils.TypeCollection); + BinaryUtils.WriteCollection(val, this); + } } /// <summary> @@ -975,10 +977,7 @@ namespace Apache.Ignite.Core.Impl.Binary { WriteFieldId(fieldName, BinaryUtils.TypeDictionary); - if (val == null) - WriteNullField(); - else - WriteDictionary(val); + WriteDictionary(val); } /// <summary> @@ -987,8 +986,13 @@ namespace Apache.Ignite.Core.Impl.Binary /// <param name="val">Dictionary.</param> public void WriteDictionary(IDictionary val) { - WriteByte(BinaryUtils.TypeDictionary); - BinaryUtils.WriteDictionary(val, this); + if (val == null) + WriteNullField(); + else + { + WriteByte(BinaryUtils.TypeDictionary); + BinaryUtils.WriteDictionary(val, this); + } } /// <summary>
