You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by pt...@apache.org on 2017/03/31 13:32:14 UTC
[1/5] ignite git commit: IGNITE-2703 .NET: Dynamic type registration
Repository: ignite
Updated Branches:
refs/heads/master 2ad2365a0 -> 79bac4f87
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/examples/Apache.Ignite.ExamplesDll/Binary/Address.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/examples/Apache.Ignite.ExamplesDll/Binary/Address.cs b/modules/platforms/dotnet/examples/Apache.Ignite.ExamplesDll/Binary/Address.cs
index 7053e78..0bacdb7 100644
--- a/modules/platforms/dotnet/examples/Apache.Ignite.ExamplesDll/Binary/Address.cs
+++ b/modules/platforms/dotnet/examples/Apache.Ignite.ExamplesDll/Binary/Address.cs
@@ -17,14 +17,12 @@
namespace Apache.Ignite.ExamplesDll.Binary
{
- using System;
using Apache.Ignite.Core.Binary;
using Apache.Ignite.Core.Cache.Configuration;
/// <summary>
/// Address.
/// </summary>
- [Serializable]
public class Address : IBinarizable
{
/// <summary>
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/examples/Apache.Ignite.ExamplesDll/Compute/CharacterCountClosure.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/examples/Apache.Ignite.ExamplesDll/Compute/CharacterCountClosure.cs b/modules/platforms/dotnet/examples/Apache.Ignite.ExamplesDll/Compute/CharacterCountClosure.cs
index a34c3fa..9d407cf 100644
--- a/modules/platforms/dotnet/examples/Apache.Ignite.ExamplesDll/Compute/CharacterCountClosure.cs
+++ b/modules/platforms/dotnet/examples/Apache.Ignite.ExamplesDll/Compute/CharacterCountClosure.cs
@@ -23,7 +23,6 @@ namespace Apache.Ignite.ExamplesDll.Compute
/// <summary>
/// Closure counting characters in a string.
/// </summary>
- [Serializable]
public class CharacterCountClosure : IComputeFunc<string, int>
{
/// <summary>
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/examples/Apache.Ignite.ExamplesDll/Datagrid/ContinuousQueryFilter.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/examples/Apache.Ignite.ExamplesDll/Datagrid/ContinuousQueryFilter.cs b/modules/platforms/dotnet/examples/Apache.Ignite.ExamplesDll/Datagrid/ContinuousQueryFilter.cs
index f569f3e..e8d4fd3 100644
--- a/modules/platforms/dotnet/examples/Apache.Ignite.ExamplesDll/Datagrid/ContinuousQueryFilter.cs
+++ b/modules/platforms/dotnet/examples/Apache.Ignite.ExamplesDll/Datagrid/ContinuousQueryFilter.cs
@@ -17,13 +17,11 @@
namespace Apache.Ignite.ExamplesDll.Datagrid
{
- using System;
using Apache.Ignite.Core.Cache.Event;
/// <summary>
/// Filter for continuous query example.
/// </summary>
- [Serializable]
public class ContinuousQueryFilter : ICacheEntryEventFilter<int, string>
{
/// <summary> Threshold. </summary>
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/examples/Apache.Ignite.ExamplesDll/Datagrid/EmployeeStorePredicate.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/examples/Apache.Ignite.ExamplesDll/Datagrid/EmployeeStorePredicate.cs b/modules/platforms/dotnet/examples/Apache.Ignite.ExamplesDll/Datagrid/EmployeeStorePredicate.cs
index 5c3bf89..1df7630 100644
--- a/modules/platforms/dotnet/examples/Apache.Ignite.ExamplesDll/Datagrid/EmployeeStorePredicate.cs
+++ b/modules/platforms/dotnet/examples/Apache.Ignite.ExamplesDll/Datagrid/EmployeeStorePredicate.cs
@@ -17,14 +17,12 @@
namespace Apache.Ignite.ExamplesDll.Datagrid
{
- using System;
using Apache.Ignite.Core.Cache;
using Apache.Ignite.ExamplesDll.Binary;
/// <summary>
/// Example cache entry predicate.
/// </summary>
- [Serializable]
public class EmployeeStorePredicate : ICacheEntryFilter<int, Employee>
{
/// <summary>
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/examples/Apache.Ignite.ExamplesDll/Messaging/RemoteOrderedListener.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/examples/Apache.Ignite.ExamplesDll/Messaging/RemoteOrderedListener.cs b/modules/platforms/dotnet/examples/Apache.Ignite.ExamplesDll/Messaging/RemoteOrderedListener.cs
index edf38f2..fd7e6ff 100644
--- a/modules/platforms/dotnet/examples/Apache.Ignite.ExamplesDll/Messaging/RemoteOrderedListener.cs
+++ b/modules/platforms/dotnet/examples/Apache.Ignite.ExamplesDll/Messaging/RemoteOrderedListener.cs
@@ -25,7 +25,6 @@ namespace Apache.Ignite.ExamplesDll.Messaging
/// <summary>
/// Listener for Ordered topic.
/// </summary>
- [Serializable]
public class RemoteOrderedListener : IMessageListener<int>
{
/** Injected Ignite instance. */
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/examples/Apache.Ignite.ExamplesDll/Messaging/RemoteUnorderedListener.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/examples/Apache.Ignite.ExamplesDll/Messaging/RemoteUnorderedListener.cs b/modules/platforms/dotnet/examples/Apache.Ignite.ExamplesDll/Messaging/RemoteUnorderedListener.cs
index 8054d36..1432f11 100644
--- a/modules/platforms/dotnet/examples/Apache.Ignite.ExamplesDll/Messaging/RemoteUnorderedListener.cs
+++ b/modules/platforms/dotnet/examples/Apache.Ignite.ExamplesDll/Messaging/RemoteUnorderedListener.cs
@@ -25,7 +25,6 @@ namespace Apache.Ignite.ExamplesDll.Messaging
/// <summary>
/// Listener for Unordered topic.
/// </summary>
- [Serializable]
public class RemoteUnorderedListener : IMessageListener<int>
{
/** Injected Ignite instance. */
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/examples/Apache.Ignite.ExamplesDll/Services/MapService.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/examples/Apache.Ignite.ExamplesDll/Services/MapService.cs b/modules/platforms/dotnet/examples/Apache.Ignite.ExamplesDll/Services/MapService.cs
index 7071cd4..8ca9ab0 100644
--- a/modules/platforms/dotnet/examples/Apache.Ignite.ExamplesDll/Services/MapService.cs
+++ b/modules/platforms/dotnet/examples/Apache.Ignite.ExamplesDll/Services/MapService.cs
@@ -26,7 +26,6 @@ namespace Apache.Ignite.ExamplesDll.Services
/// <summary>
/// Service implementation.
/// </summary>
- [Serializable]
public class MapService<TK, TV> : IService
{
/** Injected Ignite instance. */
[4/5] ignite git commit: IGNITE-2703 .NET: Dynamic type registration
Posted by pt...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/Serializable/CallbacksTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/Serializable/CallbacksTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/Serializable/CallbacksTest.cs
new file mode 100644
index 0000000..a014205
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/Serializable/CallbacksTest.cs
@@ -0,0 +1,369 @@
+\ufeff/*
+ * 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.Tests.Binary.Serializable
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Runtime.Serialization;
+ using Apache.Ignite.Core.Binary;
+ using Apache.Ignite.Core.Impl.Binary;
+ using NUnit.Framework;
+
+ /// <summary>
+ /// Tests that deserialization callbacks are invoked correctly.
+ /// </summary>
+ public class CallbacksTest
+ {
+ /** Deserialization messages. */
+ private static readonly List<string> Messages = new List<string>();
+
+ /// <summary>
+ /// Tests that callbacks are invoked in correct order on class with ISerializable interface.
+ /// </summary>
+ [Test]
+ public void TestSerializable()
+ {
+ CheckCallbacks<SerCallbacks>(true);
+ }
+
+ /// <summary>
+ /// Tests that callbacks are invoked in correct order on class without ISerializable interface.
+ /// </summary>
+ [Test]
+ public void TestNonSerializable()
+ {
+ CheckCallbacks<SerCallbacksNoInterface>(false);
+ }
+
+ /// <summary>
+ /// Tests that callbacks are invoked in correct order on class with ISerializable interface.
+ /// </summary>
+ [Test]
+ public void TestSerializableStruct()
+ {
+ var obj = new SerCallbacksStruct
+ {
+ Name = "Foo",
+ Inner = new SerCallbacksStruct
+ {
+ Name = "Bar"
+ }
+ };
+
+ Messages.Clear();
+ var res = TestUtils.SerializeDeserialize(obj);
+
+ Assert.AreEqual("Foo", res.Name);
+ Assert.AreEqual("Bar", ((SerCallbacksStruct) res.Inner).Name);
+
+ // OnDeserialization callbacks should be called AFTER entire tree is deserialized.
+ // Other callbacks order is not strictly defined.
+ var expected = new[]
+ {
+ "Foo.OnSerializing",
+ "Bar.OnSerializing",
+ "Bar.OnSerialized",
+ "Foo.OnSerialized",
+ ".OnDeserializing",
+ ".OnDeserializing",
+ "Bar.ctor",
+ "Bar.OnDeserialized",
+ "Foo.ctor",
+ "Foo.OnDeserialized",
+ "Foo.OnDeserialization",
+ "Bar.OnDeserialization",
+ };
+
+ Assert.AreEqual(expected, Messages);
+ }
+
+ /// <summary>
+ /// Tests that callbacks are invoked in correct order on class without ISerializable interface.
+ /// </summary>
+ [Test]
+ public void TestNonSerializableStruct()
+ {
+ var obj = new SerCallbacksStructNoInterface
+ {
+ Name = "Foo",
+ Inner = new SerCallbacksStructNoInterface
+ {
+ Name = "Bar"
+ }
+ };
+
+ Messages.Clear();
+ var res = TestUtils.SerializeDeserialize(obj);
+
+ Assert.AreEqual("Foo", res.Name);
+ Assert.AreEqual("Bar", ((SerCallbacksStructNoInterface) res.Inner).Name);
+
+ // OnDeserialization callbacks should be called AFTER entire tree is deserialized.
+ // Other callbacks order is not strictly defined.
+ var expected = new[]
+ {
+ "Foo.OnSerializing",
+ "Bar.OnSerializing",
+ "Bar.OnSerialized",
+ "Foo.OnSerialized",
+ ".OnDeserializing",
+ ".OnDeserializing",
+ "Bar.OnDeserialized",
+ "Foo.OnDeserialized",
+ "Foo.OnDeserialization",
+ "Bar.OnDeserialization",
+ };
+
+ Assert.AreEqual(expected, Messages);
+ }
+
+ /// <summary>
+ /// Checks the callbacks.
+ /// </summary>
+ private static void CheckCallbacks<T>(bool ctorCall) where T : SerCallbacksNoInterface, new()
+ {
+ var obj = new T
+ {
+ Name = "Foo",
+ Inner = new T
+ {
+ Name = "Bar",
+ Inner = new T
+ {
+ Name = "Baz"
+ }
+ }
+ };
+
+ Messages.Clear();
+ var res = TestUtils.SerializeDeserialize(obj);
+
+ Assert.AreEqual("Foo", res.Name);
+ Assert.AreEqual("Bar", res.Inner.Name);
+ Assert.AreEqual("Baz", res.Inner.Inner.Name);
+
+ // OnDeserialization callbacks should be called AFTER entire tree is deserialized.
+ // Other callbacks order is not strictly defined.
+ var expected = new[]
+ {
+ "Foo.OnSerializing",
+ "Bar.OnSerializing",
+ "Baz.OnSerializing",
+ "Baz.OnSerialized",
+ "Bar.OnSerialized",
+ "Foo.OnSerialized",
+ ".OnDeserializing",
+ ".OnDeserializing",
+ ".OnDeserializing",
+ "Baz.ctor",
+ "Baz.OnDeserialized",
+ "Bar.ctor",
+ "Bar.OnDeserialized",
+ "Foo.ctor",
+ "Foo.OnDeserialized",
+ "Foo.OnDeserialization",
+ "Bar.OnDeserialization",
+ "Baz.OnDeserialization"
+ };
+
+ if (!ctorCall)
+ expected = expected.Where(x => !x.Contains("ctor")).ToArray();
+
+ Assert.AreEqual(expected, Messages);
+ }
+
+ /// <summary>
+ /// Tests that incorrect method signature causes a descriptive exception.
+ /// </summary>
+ [Test]
+ public void TestIncorrectMethodSignature()
+ {
+ var ex = Assert.Throws<TypeLoadException>(
+ () => TestUtils.SerializeDeserialize(new InvalidCallbackSignature()));
+
+ var t = typeof(InvalidCallbackSignature);
+
+ Assert.AreEqual(string.Format("Type '{0}' in assembly '{1}' has method 'OnDeserializing' " +
+ "with an incorrect signature for the serialization attribute that it " +
+ "is decorated with.", t, t.Assembly), ex.Message);
+ }
+
+ /// <summary>
+ /// Class with serialization callbacks and <see cref="ISerializable" /> implemented.
+ /// This goes through <see cref="SerializableSerializer"/>.
+ /// </summary>
+ [Serializable]
+ private class SerCallbacks : SerCallbacksNoInterface, ISerializable
+ {
+ public SerCallbacks()
+ {
+ }
+
+ protected SerCallbacks(SerializationInfo info, StreamingContext context)
+ {
+ Name = info.GetString("name");
+ Inner = (SerCallbacks) info.GetValue("inner", typeof(SerCallbacks));
+
+ Messages.Add(string.Format("{0}.ctor", Name));
+ }
+
+ public void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ info.AddValue("name", Name);
+ info.AddValue("inner", Inner);
+ }
+ }
+
+ /// <summary>
+ /// Class with serialization callbacks and without <see cref="ISerializable" /> implemented.
+ /// This goes through <see cref="BinaryReflectiveSerializer"/>.
+ /// </summary>
+ [Serializable]
+ private class SerCallbacksNoInterface : IDeserializationCallback
+ {
+ public string Name { get; set; }
+
+ public SerCallbacksNoInterface Inner { get; set; }
+
+ public void OnDeserialization(object sender)
+ {
+ Messages.Add(string.Format("{0}.OnDeserialization", Name));
+ }
+
+ [OnSerializing]
+ public void OnSerializing(StreamingContext context)
+ {
+ Messages.Add(string.Format("{0}.OnSerializing", Name));
+ }
+
+ [OnSerialized]
+ public void OnSerialized(StreamingContext context)
+ {
+ Messages.Add(string.Format("{0}.OnSerialized", Name));
+ }
+
+ [OnDeserializing]
+ public void OnDeserializing(StreamingContext context)
+ {
+ Messages.Add(string.Format("{0}.OnDeserializing", Name));
+ }
+
+ [OnDeserialized]
+ public void OnDeserialized(StreamingContext context)
+ {
+ Messages.Add(string.Format("{0}.OnDeserialized", Name));
+ }
+ }
+
+ private class InvalidCallbackSignature
+ {
+ [OnDeserializing]
+ public void OnDeserializing()
+ {
+ // No-op.
+ }
+ }
+
+ [Serializable]
+ private struct SerCallbacksStruct : IDeserializationCallback, ISerializable
+ {
+ public string Name { get; set; }
+
+ public object Inner { get; set; }
+
+ public SerCallbacksStruct(SerializationInfo info, StreamingContext context) : this()
+ {
+ Name = info.GetString("name");
+ Inner = info.GetValue("inner", typeof(object));
+ Messages.Add(string.Format("{0}.ctor", Name));
+ }
+
+ public void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ info.AddValue("name", Name);
+ info.AddValue("inner", Inner);
+ }
+
+ public void OnDeserialization(object sender)
+ {
+ Messages.Add(string.Format("{0}.OnDeserialization", Name));
+ }
+
+ [OnSerializing]
+ public void OnSerializing(StreamingContext context)
+ {
+ Messages.Add(string.Format("{0}.OnSerializing", Name));
+ }
+
+ [OnSerialized]
+ public void OnSerialized(StreamingContext context)
+ {
+ Messages.Add(string.Format("{0}.OnSerialized", Name));
+ }
+
+ [OnDeserializing]
+ public void OnDeserializing(StreamingContext context)
+ {
+ Messages.Add(string.Format("{0}.OnDeserializing", Name));
+ }
+
+ [OnDeserialized]
+ public void OnDeserialized(StreamingContext context)
+ {
+ Messages.Add(string.Format("{0}.OnDeserialized", Name));
+ }
+ }
+
+ private struct SerCallbacksStructNoInterface : IDeserializationCallback
+ {
+ public string Name { get; set; }
+
+ public object Inner { get; set; }
+
+ public void OnDeserialization(object sender)
+ {
+ Messages.Add(string.Format("{0}.OnDeserialization", Name));
+ }
+
+ [OnSerializing]
+ public void OnSerializing(StreamingContext context)
+ {
+ Messages.Add(string.Format("{0}.OnSerializing", Name));
+ }
+
+ [OnSerialized]
+ public void OnSerialized(StreamingContext context)
+ {
+ Messages.Add(string.Format("{0}.OnSerialized", Name));
+ }
+
+ [OnDeserializing]
+ public void OnDeserializing(StreamingContext context)
+ {
+ Messages.Add(string.Format("{0}.OnDeserializing", Name));
+ }
+
+ [OnDeserialized]
+ public void OnDeserialized(StreamingContext context)
+ {
+ Messages.Add(string.Format("{0}.OnDeserialized", Name));
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/Serializable/DelegatesTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/Serializable/DelegatesTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/Serializable/DelegatesTest.cs
new file mode 100644
index 0000000..90720d4
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/Serializable/DelegatesTest.cs
@@ -0,0 +1,161 @@
+\ufeff/*
+ * 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.Tests.Binary.Serializable
+{
+ using System;
+ using System.Reflection;
+ using NUnit.Framework;
+
+ /// <summary>
+ /// Tests delegate serialization.
+ /// </summary>
+ public class DelegatesTest
+ {
+ /** Test int value. */
+ private static int _int;
+
+ /** Test delegate. */
+ private delegate string LowerSubStringDelegate(string s, int startIndex);
+
+ /// <summary>
+ /// Tests that delegates can be serialized.
+ /// </summary>
+ [Test]
+ public void TestAction()
+ {
+ // Action with captured variable.
+ var val = new PrimitivesTest.Primitives {Int = 135};
+
+ Action act = () => {
+ val.Int++;
+ _int = val.Int;
+ };
+
+ var res = TestUtils.SerializeDeserialize(act);
+ Assert.AreEqual(act.Method, res.Method);
+ Assert.AreNotEqual(act.Target, res.Target);
+
+ res();
+ Assert.AreEqual(135, val.Int); // Captured variable is deserialized to a new instance.
+ Assert.AreEqual(136, _int);
+
+ // Action with arguments.
+ Action<PrimitivesTest.Primitives, int> act1 = (p, i) => { p.Int = i; };
+
+ var res1 = TestUtils.SerializeDeserialize(act1);
+ Assert.AreEqual(act1.Method, res1.Method);
+
+ res1(val, 33);
+ Assert.AreEqual(33, val.Int);
+ }
+
+ /// <summary>
+ /// Tests that anonymous function can be serialized.
+ /// </summary>
+ [Test]
+ public void TestFunc()
+ {
+ int ms = DateTime.Now.Millisecond;
+
+ Func<int, int> func = x => x + ms;
+
+ var resFunc = TestUtils.SerializeDeserialize(func);
+ Assert.AreEqual(func.Method, resFunc.Method);
+ Assert.AreNotEqual(func.Target, resFunc.Target);
+
+ Assert.AreEqual(ms + 20, resFunc(20));
+ }
+
+ /// <summary>
+ /// Tests that old-fashioned delegate can be serialized.
+ /// </summary>
+ [Test]
+ public void TestDelegate()
+ {
+ // Delegate to a static method.
+ LowerSubStringDelegate del1 = LowerSubString;
+
+ var del1Res = TestUtils.SerializeDeserialize(del1);
+
+ Assert.AreEqual(del1.Method, del1Res.Method);
+ Assert.IsNull(del1Res.Target);
+
+ Assert.AreEqual("ooz", del1Res("FOOZ", 1));
+
+ // Delegate to an anonymous method.
+ LowerSubStringDelegate del2 = (s, i) => s.Substring(i).ToLower();
+
+ var del2Res = TestUtils.SerializeDeserialize(del2);
+
+ Assert.AreEqual(del2.Method, del2Res.Method, "Delegate methods are same");
+
+ Assert.AreEqual("ooz", del2Res("FOOZ", 1), "Delegate works as expected");
+ }
+
+ /// <summary>
+ /// Tests that MethodInfo can be serialized.
+ /// </summary>
+ [Test]
+ public void TestMethodInfo()
+ {
+ var methods = typeof(string).GetMethods(BindingFlags.Public | BindingFlags.NonPublic
+ | BindingFlags.Instance | BindingFlags.Static);
+
+ Assert.IsNotEmpty(methods);
+
+ foreach (var methodInfo in methods)
+ {
+ var res = TestUtils.SerializeDeserialize(methodInfo);
+
+ Assert.AreEqual(methodInfo.Name, res.Name);
+ Assert.AreEqual(methodInfo.DeclaringType, res.DeclaringType);
+ Assert.AreEqual(methodInfo.ReturnType, res.ReturnType);
+ Assert.AreEqual(methodInfo.GetParameters(), res.GetParameters());
+ }
+ }
+
+ /// <summary>
+ /// Tests that recursive anonymous function can be serialized.
+ /// </summary>
+ [Test]
+ public void TestRecursiveFunc()
+ {
+ Func<int, int> fib = null;
+ fib = x => x == 0
+ ? 0
+ : x == 1
+ ? 1
+ : fib(x - 2) + fib(x - 1);
+
+ Assert.AreEqual(89, fib(11));
+ Assert.AreEqual(144, fib(12));
+
+ var resFib = TestUtils.SerializeDeserialize(fib);
+
+ Assert.AreEqual(fib.Method, resFib.Method);
+
+ Assert.AreEqual(89, resFib(11));
+ Assert.AreEqual(144, resFib(12));
+ }
+
+ private static string LowerSubString(string s, int startIndex)
+ {
+ return s.Substring(startIndex).ToLower();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/Serializable/ObjectReferenceTests.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/Serializable/ObjectReferenceTests.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/Serializable/ObjectReferenceTests.cs
new file mode 100644
index 0000000..71d2f9a
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/Serializable/ObjectReferenceTests.cs
@@ -0,0 +1,131 @@
+\ufeff/*
+ * 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.Tests.Binary.Serializable
+{
+ using System;
+ using System.Runtime.Serialization;
+ using NUnit.Framework;
+
+ /// <summary>
+ /// Tests that <see cref="IObjectReference"/> objects are deserialized properly.
+ /// This only applies to <see cref="ISerializable"/> implementers, which can replace underlying object
+ /// with <see cref="SerializationInfo.SetType"/>, <see cref="SerializationInfo.AssemblyName"/>, and
+ /// <see cref="SerializationInfo.FullTypeName"/>.
+ /// </summary>
+ public class ObjectReferenceTests
+ {
+ /// <summary>
+ /// Tests serialization object replacement with <see cref="SerializationInfo.SetType"/> method.
+ /// </summary>
+ [Test]
+ public void TestSetType()
+ {
+ var obj = new SetTypeReplacer(25);
+
+ var res = TestUtils.SerializeDeserialize(obj);
+
+ Assert.AreEqual(obj.Value, res.Value);
+ }
+
+ /// <summary>
+ /// Tests serialization object replacement with <see cref="SerializationInfo.FullTypeName"/> property.
+ /// </summary>
+ [Test]
+ public void TestTypeName()
+ {
+ var obj = new TypeNameReplacer(36);
+
+ var res = TestUtils.SerializeDeserialize(obj);
+
+ Assert.AreEqual(obj.Value, res.Value);
+ }
+
+ [Serializable]
+ private class SetTypeReplacer : ISerializable
+ {
+ private readonly int _value;
+
+ public SetTypeReplacer(int value)
+ {
+ _value = value;
+ }
+
+ public int Value
+ {
+ get { return _value; }
+ }
+
+ public void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ info.SetType(typeof(ObjectInfoHolder));
+
+ info.AddValue("type", GetType());
+ info.AddValue("val", Value);
+ }
+ }
+
+ [Serializable]
+ private class TypeNameReplacer : ISerializable
+ {
+ private readonly int _value;
+
+ public TypeNameReplacer(int value)
+ {
+ _value = value;
+ }
+
+ public int Value
+ {
+ get { return _value; }
+ }
+
+ public void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ info.FullTypeName = typeof(ObjectInfoHolder).FullName;
+ info.AssemblyName = typeof(ObjectInfoHolder).Assembly.FullName;
+
+ info.AddValue("type", GetType());
+ info.AddValue("val", Value);
+ }
+ }
+
+ [Serializable]
+ private class ObjectInfoHolder : IObjectReference, ISerializable
+ {
+ public Type ObjectType { get; set; }
+
+ public int Value { get; set; }
+
+ public object GetRealObject(StreamingContext context)
+ {
+ return Activator.CreateInstance(ObjectType, Value);
+ }
+
+ public ObjectInfoHolder(SerializationInfo info, StreamingContext context)
+ {
+ ObjectType = (Type) info.GetValue("type", typeof(Type));
+ Value = info.GetInt32("val");
+ }
+
+ public void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ // No-op.
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/Serializable/PrimitivesTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/Serializable/PrimitivesTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/Serializable/PrimitivesTest.cs
new file mode 100644
index 0000000..bbbee60
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/Serializable/PrimitivesTest.cs
@@ -0,0 +1,754 @@
+\ufeff/*
+ * 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.
+ */
+
+// ReSharper disable StringLiteralTypo
+// ReSharper disable IdentifierTypo
+namespace Apache.Ignite.Core.Tests.Binary.Serializable
+{
+ using System;
+ using System.Linq;
+ using System.Runtime.Serialization;
+ using Apache.Ignite.Core.Binary;
+ using Apache.Ignite.Core.Impl;
+ using Apache.Ignite.Core.Impl.Binary;
+ using NUnit.Framework;
+
+ /// <summary>
+ /// Tests [Serializable] mechanism handling primitive types.
+ /// </summary>
+ public class PrimitivesTest
+ {
+ /** */
+ private IIgnite _ignite;
+
+ /// <summary>
+ /// Sets up the test fixture.
+ /// </summary>
+ [TestFixtureSetUp]
+ public void FixtureSetUp()
+ {
+ _ignite = Ignition.Start(TestUtils.GetTestConfiguration());
+ }
+
+ /// <summary>
+ /// Tears down the test fixture.
+ /// </summary>
+ [TestFixtureTearDown]
+ public void FixtureTearDown()
+ {
+ Ignition.StopAll(true);
+ }
+
+ /// <summary>
+ /// Tests the DateTime which is ISerializable struct.
+ /// </summary>
+ [Test]
+ public void TestDateTime()
+ {
+ var marsh = GetMarshaller();
+
+ var val = DateTime.Now;
+
+ Assert.AreEqual(val, marsh.Unmarshal<DateTime>(marsh.Marshal(val)));
+
+ Assert.AreEqual(new[] {val}, marsh.Unmarshal<DateTime[]>(marsh.Marshal(new[] {val})));
+
+ Assert.AreEqual(new DateTime?[] {val, null},
+ marsh.Unmarshal<DateTime?[]>(marsh.Marshal(new DateTime?[] {val, null})));
+ }
+
+ /// <summary>
+ /// Tests that primitive types can be serialized with ISerializable mechanism.
+ /// </summary>
+ [Test]
+ public void TestPrimitives()
+ {
+ var marsh = GetMarshaller();
+
+ var val1 = new Primitives
+ {
+ Byte = 1,
+ Bytes = new byte[] {2, 3, byte.MinValue, byte.MaxValue},
+ Sbyte = -64,
+ Sbytes = new sbyte[] {sbyte.MinValue, sbyte.MaxValue, 1, 2, -4, -5},
+ Bool = true,
+ Bools = new[] {true, true, false},
+ Char = 'x',
+ Chars = new[] {'a', 'z', char.MinValue, char.MaxValue},
+ Short = -25,
+ Shorts = new short[] {5, -7, 9, short.MinValue, short.MaxValue},
+ Ushort = 99,
+ Ushorts = new ushort[] {10, 20, 12, ushort.MinValue, ushort.MaxValue},
+ Int = -456,
+ Ints = new[] {-100, 200, -300, int.MinValue, int.MaxValue},
+ Uint = 456,
+ Uints = new uint[] {100, 200, 300, uint.MinValue, uint.MaxValue},
+ Long = long.MaxValue,
+ Longs = new[] {long.MinValue, long.MaxValue, 33, -44},
+ Ulong = ulong.MaxValue,
+ Ulongs = new ulong[] {ulong.MinValue, ulong.MaxValue, 33},
+ Float = 1.33f,
+ Floats = new[]
+ {
+ float.MinValue, float.MaxValue,
+ float.Epsilon, float.NegativeInfinity, float.PositiveInfinity, float.NaN,
+ 1.23f, -2.5f
+ },
+ Double = -6.78,
+ Doubles = new[]
+ {
+ double.MinValue, double.MaxValue, double.Epsilon,
+ double.NegativeInfinity, double.PositiveInfinity,
+ 3.76, -9.89
+ },
+ Decimal = 1.23456789m,
+ Decimals = new[]
+ {
+ decimal.MinValue, decimal.MaxValue, decimal.One, decimal.MinusOne, decimal.Zero,
+ 1.35m, -2.46m
+ },
+ DateTime = DateTime.UtcNow,
+ DateTimes = new[] {DateTime.Now, DateTime.MinValue, DateTime.MaxValue, DateTime.UtcNow},
+ Guid = Guid.NewGuid(),
+ Guids = new[] {Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid()},
+ String = "hello world",
+ Strings = new[] {"hello", "world"}
+ };
+
+ var vals = new[] {new Primitives(), val1};
+
+ foreach (var val in vals)
+ {
+ Assert.IsFalse(val.GetObjectDataCalled);
+ Assert.IsFalse(val.SerializationCtorCalled);
+
+ // Unmarshal in full and binary form.
+ var bytes = marsh.Marshal(val);
+ var res = marsh.Unmarshal<Primitives>(bytes);
+ var bin = marsh.Unmarshal<IBinaryObject>(bytes, BinaryMode.ForceBinary);
+
+ // Verify flags.
+ Assert.IsTrue(val.GetObjectDataCalled);
+ Assert.IsFalse(val.SerializationCtorCalled);
+
+ Assert.IsFalse(res.GetObjectDataCalled);
+ Assert.IsTrue(res.SerializationCtorCalled);
+
+ // Verify values.
+ Assert.AreEqual(val.Byte, res.Byte);
+ Assert.AreEqual(val.Byte, bin.GetField<byte>("byte"));
+
+ Assert.AreEqual(val.Bytes, res.Bytes);
+ Assert.AreEqual(val.Bytes, bin.GetField<byte[]>("bytes"));
+
+ Assert.AreEqual(val.Sbyte, res.Sbyte);
+ Assert.AreEqual(val.Sbyte, bin.GetField<sbyte>("sbyte"));
+
+ Assert.AreEqual(val.Sbytes, res.Sbytes);
+ Assert.AreEqual(val.Sbytes, bin.GetField<sbyte[]>("sbytes"));
+
+ Assert.AreEqual(val.Bool, res.Bool);
+ Assert.AreEqual(val.Bool, bin.GetField<bool>("bool"));
+
+ Assert.AreEqual(val.Bools, res.Bools);
+ Assert.AreEqual(val.Bools, bin.GetField<bool[]>("bools"));
+
+ Assert.AreEqual(val.Char, res.Char);
+ Assert.AreEqual(val.Char, bin.GetField<char>("char"));
+
+ Assert.AreEqual(val.Chars, res.Chars);
+ Assert.AreEqual(val.Chars, bin.GetField<char[]>("chars"));
+
+ Assert.AreEqual(val.Short, res.Short);
+ Assert.AreEqual(val.Short, bin.GetField<short>("short"));
+
+ Assert.AreEqual(val.Shorts, res.Shorts);
+ Assert.AreEqual(val.Shorts, bin.GetField<short[]>("shorts"));
+
+ Assert.AreEqual(val.Ushort, res.Ushort);
+ Assert.AreEqual(val.Ushort, bin.GetField<ushort>("ushort"));
+
+ Assert.AreEqual(val.Ushorts, res.Ushorts);
+ Assert.AreEqual(val.Ushorts, bin.GetField<ushort[]>("ushorts"));
+
+ Assert.AreEqual(val.Int, res.Int);
+ Assert.AreEqual(val.Int, bin.GetField<int>("int"));
+
+ Assert.AreEqual(val.Ints, res.Ints);
+ Assert.AreEqual(val.Ints, bin.GetField<int[]>("ints"));
+
+ Assert.AreEqual(val.Uint, res.Uint);
+ Assert.AreEqual(val.Uint, bin.GetField<uint>("uint"));
+
+ Assert.AreEqual(val.Uints, res.Uints);
+ Assert.AreEqual(val.Uints, bin.GetField<uint[]>("uints"));
+
+ Assert.AreEqual(val.Long, res.Long);
+ Assert.AreEqual(val.Long, bin.GetField<long>("long"));
+
+ Assert.AreEqual(val.Longs, res.Longs);
+ Assert.AreEqual(val.Longs, bin.GetField<long[]>("longs"));
+
+ Assert.AreEqual(val.Ulong, res.Ulong);
+ Assert.AreEqual(val.Ulong, bin.GetField<ulong>("ulong"));
+
+ Assert.AreEqual(val.Ulongs, res.Ulongs);
+ Assert.AreEqual(val.Ulongs, bin.GetField<ulong[]>("ulongs"));
+
+ Assert.AreEqual(val.Float, res.Float);
+ Assert.AreEqual(val.Float, bin.GetField<float>("float"));
+
+ Assert.AreEqual(val.Floats, res.Floats);
+ Assert.AreEqual(val.Floats, bin.GetField<float[]>("floats"));
+
+ Assert.AreEqual(val.Double, res.Double);
+ Assert.AreEqual(val.Double, bin.GetField<double>("double"));
+
+ Assert.AreEqual(val.Doubles, res.Doubles);
+ Assert.AreEqual(val.Doubles, bin.GetField<double[]>("doubles"));
+
+ Assert.AreEqual(val.Decimal, res.Decimal);
+ Assert.AreEqual(val.Decimal, bin.GetField<decimal>("decimal"));
+
+ Assert.AreEqual(val.Decimals, res.Decimals);
+ Assert.AreEqual(val.Decimals, bin.GetField<decimal[]>("decimals"));
+
+ Assert.AreEqual(val.Guid, res.Guid);
+ Assert.AreEqual(val.Guid, bin.GetField<Guid>("guid"));
+
+ Assert.AreEqual(val.Guids, res.Guids);
+ Assert.AreEqual(val.Guids, bin.GetField<Guid[]>("guids"));
+
+ Assert.AreEqual(val.DateTime, res.DateTime);
+ Assert.AreEqual(val.DateTime, bin.GetField<IBinaryObject>("datetime").Deserialize<DateTime>());
+
+ Assert.AreEqual(val.DateTimes, res.DateTimes);
+ var dts = bin.GetField<IBinaryObject[]>("datetimes");
+ Assert.AreEqual(val.DateTimes, dts == null ? null : dts.Select(x => x.Deserialize<DateTime>()));
+
+ Assert.AreEqual(val.String, res.String);
+ Assert.AreEqual(val.String, bin.GetField<string>("string"));
+
+ Assert.AreEqual(val.Strings, res.Strings);
+ Assert.AreEqual(val.Strings, bin.GetField<string[]>("strings"));
+
+ VerifyFieldTypes(bin);
+ }
+ }
+
+ /// <summary>
+ /// Tests that primitive types in nullable form can be serialized with ISerializable mechanism.
+ /// </summary>
+ [Test]
+ public void TestPrimitivesNullable()
+ {
+ var marsh = GetMarshaller();
+
+ var val1 = new PrimitivesNullable
+ {
+ Byte = 1,
+ Bytes = new byte?[] {2, 3, byte.MinValue, byte.MaxValue, null},
+ Sbyte = -64,
+ Sbytes = new sbyte?[] {sbyte.MinValue, sbyte.MaxValue, 1, 2, -4, -5, null},
+ Bool = true,
+ Bools = new bool?[] {true, true, false, null},
+ Char = 'x',
+ Chars = new char?[] {'a', 'z', char.MinValue, char.MaxValue, null},
+ Short = -25,
+ Shorts = new short?[] {5, -7, 9, short.MinValue, short.MaxValue, null},
+ Ushort = 99,
+ Ushorts = new ushort?[] {10, 20, 12, ushort.MinValue, ushort.MaxValue, null},
+ Int = -456,
+ Ints = new int?[] {-100, 200, -300, int.MinValue, int.MaxValue, null},
+ Uint = 456,
+ Uints = new uint?[] {100, 200, 300, uint.MinValue, uint.MaxValue, null},
+ Long = long.MaxValue,
+ Longs = new long?[] {long.MinValue, long.MaxValue, 33, -44, null},
+ Ulong = ulong.MaxValue,
+ Ulongs = new ulong?[] {ulong.MinValue, ulong.MaxValue, 33, null},
+ Float = 1.33f,
+ Floats = new float?[]
+ {
+ float.MinValue, float.MaxValue,
+ float.Epsilon, float.NegativeInfinity, float.PositiveInfinity, float.NaN,
+ 1.23f, -2.5f, null
+ },
+ Double = -6.78,
+ Doubles = new double?[]
+ {
+ double.MinValue, double.MaxValue, double.Epsilon,
+ double.NegativeInfinity, double.PositiveInfinity,
+ 3.76, -9.89, null
+ },
+ Decimal = 1.23456789m,
+ Decimals = new decimal?[]
+ {
+ decimal.MinValue, decimal.MaxValue, decimal.One, decimal.MinusOne, decimal.Zero,
+ 1.35m, -2.46m, null
+ },
+ DateTime = DateTime.UtcNow,
+ DateTimes = new DateTime?[]
+ {
+ DateTime.Now, DateTime.MinValue, DateTime.MaxValue, DateTime.UtcNow, null
+ },
+ Guid = Guid.NewGuid(),
+ Guids = new Guid?[] {Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid(), null},
+ };
+
+ var vals = new[] {new PrimitivesNullable(), val1};
+
+ foreach (var val in vals)
+ {
+ Assert.IsFalse(val.GetObjectDataCalled);
+ Assert.IsFalse(val.SerializationCtorCalled);
+
+ // Unmarshal in full and binary form.
+ var bytes = marsh.Marshal(val);
+ var res = marsh.Unmarshal<PrimitivesNullable>(bytes);
+ var bin = marsh.Unmarshal<IBinaryObject>(bytes, BinaryMode.ForceBinary);
+
+ // Verify flags.
+ Assert.IsTrue(val.GetObjectDataCalled);
+ Assert.IsFalse(val.SerializationCtorCalled);
+
+ Assert.IsFalse(res.GetObjectDataCalled);
+ Assert.IsTrue(res.SerializationCtorCalled);
+
+ // Verify values.
+ Assert.AreEqual(val.Byte, res.Byte);
+ Assert.AreEqual(val.Byte, bin.GetField<byte?>("byte"));
+
+ Assert.AreEqual(val.Bytes, res.Bytes);
+ Assert.AreEqual(val.Bytes, bin.GetField<byte?[]>("bytes"));
+
+ Assert.AreEqual(val.Sbyte, res.Sbyte);
+ Assert.AreEqual(val.Sbyte, bin.GetField<sbyte?>("sbyte"));
+
+ Assert.AreEqual(val.Sbytes, res.Sbytes);
+ Assert.AreEqual(val.Sbytes, bin.GetField<sbyte?[]>("sbytes"));
+
+ Assert.AreEqual(val.Bool, res.Bool);
+ Assert.AreEqual(val.Bool, bin.GetField<bool?>("bool"));
+
+ Assert.AreEqual(val.Bools, res.Bools);
+ Assert.AreEqual(val.Bools, bin.GetField<bool?[]>("bools"));
+
+ Assert.AreEqual(val.Char, res.Char);
+ Assert.AreEqual(val.Char, bin.GetField<char?>("char"));
+
+ Assert.AreEqual(val.Chars, res.Chars);
+ Assert.AreEqual(val.Chars, bin.GetField<char?[]>("chars"));
+
+ Assert.AreEqual(val.Short, res.Short);
+ Assert.AreEqual(val.Short, bin.GetField<short?>("short"));
+
+ Assert.AreEqual(val.Shorts, res.Shorts);
+ Assert.AreEqual(val.Shorts, bin.GetField<short?[]>("shorts"));
+
+ Assert.AreEqual(val.Ushort, res.Ushort);
+ Assert.AreEqual(val.Ushort, bin.GetField<ushort?>("ushort"));
+
+ Assert.AreEqual(val.Ushorts, res.Ushorts);
+ Assert.AreEqual(val.Ushorts, bin.GetField<ushort?[]>("ushorts"));
+
+ Assert.AreEqual(val.Int, res.Int);
+ Assert.AreEqual(val.Int, bin.GetField<int?>("int"));
+
+ Assert.AreEqual(val.Ints, res.Ints);
+ Assert.AreEqual(val.Ints, bin.GetField<int?[]>("ints"));
+
+ Assert.AreEqual(val.Uint, res.Uint);
+ Assert.AreEqual(val.Uint, bin.GetField<uint?>("uint"));
+
+ Assert.AreEqual(val.Uints, res.Uints);
+ Assert.AreEqual(val.Uints, bin.GetField<uint?[]>("uints"));
+
+ Assert.AreEqual(val.Long, res.Long);
+ Assert.AreEqual(val.Long, bin.GetField<long?>("long"));
+
+ Assert.AreEqual(val.Longs, res.Longs);
+ Assert.AreEqual(val.Longs, bin.GetField<long?[]>("longs"));
+
+ Assert.AreEqual(val.Ulong, res.Ulong);
+ Assert.AreEqual(val.Ulong, bin.GetField<ulong?>("ulong"));
+
+ Assert.AreEqual(val.Ulongs, res.Ulongs);
+ Assert.AreEqual(val.Ulongs, bin.GetField<ulong?[]>("ulongs"));
+
+ Assert.AreEqual(val.Float, res.Float);
+ Assert.AreEqual(val.Float, bin.GetField<float?>("float"));
+
+ Assert.AreEqual(val.Floats, res.Floats);
+ Assert.AreEqual(val.Floats, bin.GetField<float?[]>("floats"));
+
+ Assert.AreEqual(val.Double, res.Double);
+ Assert.AreEqual(val.Double, bin.GetField<double?>("double"));
+
+ Assert.AreEqual(val.Doubles, res.Doubles);
+ Assert.AreEqual(val.Doubles, bin.GetField<double?[]>("doubles"));
+
+ Assert.AreEqual(val.Decimal, res.Decimal);
+ Assert.AreEqual(val.Decimal, bin.GetField<decimal?>("decimal"));
+
+ Assert.AreEqual(val.Decimals, res.Decimals);
+ Assert.AreEqual(val.Decimals, bin.GetField<decimal?[]>("decimals"));
+
+ Assert.AreEqual(val.Guid, res.Guid);
+ Assert.AreEqual(val.Guid, bin.GetField<Guid?>("guid"));
+
+ Assert.AreEqual(val.Guids, res.Guids);
+ Assert.AreEqual(val.Guids, bin.GetField<Guid?[]>("guids"));
+
+ Assert.AreEqual(val.DateTime, res.DateTime);
+ var dt = bin.GetField<IBinaryObject>("datetime");
+ Assert.AreEqual(val.DateTime, dt == null ? null : dt.Deserialize<DateTime?>());
+
+ Assert.AreEqual(val.DateTimes, res.DateTimes);
+ var dts = bin.GetField<IBinaryObject[]>("datetimes");
+ Assert.AreEqual(val.DateTimes, dts == null
+ ? null
+ : dts.Select(x => x == null ? null : x.Deserialize<DateTime?>()));
+ }
+ }
+
+ /// <summary>
+ /// Verifies the field types.
+ /// </summary>
+ private static void VerifyFieldTypes(IBinaryObject bin)
+ {
+ var binType = bin.GetBinaryType();
+
+ Assert.AreEqual("byte", binType.GetFieldTypeName("byte"));
+ Assert.AreEqual("byte", binType.GetFieldTypeName("sbyte"));
+
+ Assert.AreEqual("byte[]", binType.GetFieldTypeName("bytes"));
+ Assert.AreEqual("byte[]", binType.GetFieldTypeName("sbytes"));
+
+ Assert.AreEqual("boolean", binType.GetFieldTypeName("bool"));
+ Assert.AreEqual("boolean[]", binType.GetFieldTypeName("bools"));
+
+ Assert.AreEqual("char", binType.GetFieldTypeName("char"));
+ Assert.AreEqual("char[]", binType.GetFieldTypeName("chars"));
+
+ Assert.AreEqual("short", binType.GetFieldTypeName("short"));
+ Assert.AreEqual("short[]", binType.GetFieldTypeName("shorts"));
+
+ Assert.AreEqual("short", binType.GetFieldTypeName("ushort"));
+ Assert.AreEqual("short[]", binType.GetFieldTypeName("ushorts"));
+
+ Assert.AreEqual("int", binType.GetFieldTypeName("int"));
+ Assert.AreEqual("int[]", binType.GetFieldTypeName("ints"));
+
+ Assert.AreEqual("int", binType.GetFieldTypeName("uint"));
+ Assert.AreEqual("int[]", binType.GetFieldTypeName("uints"));
+
+ Assert.AreEqual("long", binType.GetFieldTypeName("long"));
+ Assert.AreEqual("long[]", binType.GetFieldTypeName("longs"));
+
+ Assert.AreEqual("long", binType.GetFieldTypeName("ulong"));
+ Assert.AreEqual("long[]", binType.GetFieldTypeName("ulongs"));
+
+ Assert.AreEqual("float", binType.GetFieldTypeName("float"));
+ Assert.AreEqual("float[]", binType.GetFieldTypeName("floats"));
+
+ Assert.AreEqual("double", binType.GetFieldTypeName("double"));
+ Assert.AreEqual("double[]", binType.GetFieldTypeName("doubles"));
+
+ Assert.AreEqual("decimal", binType.GetFieldTypeName("decimal"));
+ Assert.AreEqual("Object", binType.GetFieldTypeName("decimals"));
+
+ Assert.AreEqual("UUID", binType.GetFieldTypeName("guid"));
+ Assert.AreEqual("Object", binType.GetFieldTypeName("guids"));
+
+ Assert.AreEqual("Object", binType.GetFieldTypeName("datetime"));
+ Assert.AreEqual("Object", binType.GetFieldTypeName("datetimes"));
+ }
+
+ /// <summary>
+ /// Gets the marshaller.
+ /// </summary>
+ private Marshaller GetMarshaller()
+ {
+ return ((Ignite) _ignite).Marshaller;
+ }
+
+ [Serializable]
+ public class Primitives : ISerializable
+ {
+ public bool GetObjectDataCalled { get; private set; }
+ public bool SerializationCtorCalled { get; private set; }
+
+ public byte Byte { get; set; }
+ public byte[] Bytes { get; set; }
+ public sbyte Sbyte { get; set; }
+ public sbyte[] Sbytes { get; set; }
+ public bool Bool { get; set; }
+ public bool[] Bools { get; set; }
+ public char Char { get; set; }
+ public char[] Chars { get; set; }
+ public short Short { get; set; }
+ public short[] Shorts { get; set; }
+ public ushort Ushort { get; set; }
+ public ushort[] Ushorts { get; set; }
+ public int Int { get; set; }
+ public int[] Ints { get; set; }
+ public uint Uint { get; set; }
+ public uint[] Uints { get; set; }
+ public long Long { get; set; }
+ public long[] Longs { get; set; }
+ public ulong Ulong { get; set; }
+ public ulong[] Ulongs { get; set; }
+ public float Float { get; set; }
+ public float[] Floats { get; set; }
+ public double Double { get; set; }
+ public double[] Doubles { get; set; }
+ public decimal Decimal { get; set; }
+ public decimal[] Decimals { get; set; }
+ public Guid Guid { get; set; }
+ public Guid[] Guids { get; set; }
+ public DateTime DateTime { get; set; }
+ public DateTime[] DateTimes { get; set; }
+ public string String { get; set; }
+ public string[] Strings { get; set; }
+
+ public Primitives()
+ {
+ // No-op.
+ }
+
+ protected Primitives(SerializationInfo info, StreamingContext context)
+ {
+ SerializationCtorCalled = true;
+
+ Byte = info.GetByte("byte");
+ Bytes = (byte[]) info.GetValue("bytes", typeof(byte[]));
+
+ Sbyte = info.GetSByte("sbyte");
+ Sbytes = (sbyte[]) info.GetValue("sbytes", typeof(sbyte[]));
+
+ Bool = info.GetBoolean("bool");
+ Bools = (bool[]) info.GetValue("bools", typeof(bool[]));
+
+ Char = info.GetChar("char");
+ Chars = (char[]) info.GetValue("chars", typeof(char[]));
+
+ Short = info.GetInt16("short");
+ Shorts = (short[]) info.GetValue("shorts", typeof(short[]));
+
+ Ushort = info.GetUInt16("ushort");
+ Ushorts = (ushort[]) info.GetValue("ushorts", typeof(ushort[]));
+
+ Int = info.GetInt32("int");
+ Ints = (int[]) info.GetValue("ints", typeof(int[]));
+
+ Uint = info.GetUInt32("uint");
+ Uints = (uint[]) info.GetValue("uints", typeof(uint[]));
+
+ Long = info.GetInt64("long");
+ Longs = (long[]) info.GetValue("longs", typeof(long[]));
+
+ Ulong = info.GetUInt64("ulong");
+ Ulongs = (ulong[]) info.GetValue("ulongs", typeof(ulong[]));
+
+ Float = info.GetSingle("float");
+ Floats = (float[]) info.GetValue("floats", typeof(float[]));
+
+ Double = info.GetDouble("double");
+ Doubles = (double[]) info.GetValue("doubles", typeof(double[]));
+
+ Decimal = info.GetDecimal("decimal");
+ Decimals = (decimal[]) info.GetValue("decimals", typeof(decimal[]));
+
+ Guid = (Guid) info.GetValue("guid", typeof(Guid));
+ Guids = (Guid[]) info.GetValue("guids", typeof(Guid[]));
+
+ DateTime = info.GetDateTime("datetime");
+ DateTimes = (DateTime[]) info.GetValue("datetimes", typeof(DateTime[]));
+
+ String = info.GetString("string");
+ Strings = (string[]) info.GetValue("strings", typeof(string[]));
+ }
+
+ public void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ GetObjectDataCalled = true;
+
+ info.AddValue("byte", Byte);
+ info.AddValue("bytes", Bytes, typeof(byte[]));
+ info.AddValue("sbyte", Sbyte);
+ info.AddValue("sbytes", Sbytes, typeof(sbyte[]));
+ info.AddValue("bool", Bool);
+ info.AddValue("bools", Bools, typeof(bool[]));
+ info.AddValue("char", Char);
+ info.AddValue("chars", Chars, typeof(char[]));
+ info.AddValue("short", Short);
+ info.AddValue("shorts", Shorts, typeof(short[]));
+ info.AddValue("ushort", Ushort);
+ info.AddValue("ushorts", Ushorts, typeof(ushort[]));
+ info.AddValue("int", Int);
+ info.AddValue("ints", Ints, typeof(int[]));
+ info.AddValue("uint", Uint);
+ info.AddValue("uints", Uints, typeof(uint[]));
+ info.AddValue("long", Long);
+ info.AddValue("longs", Longs, typeof(long[]));
+ info.AddValue("ulong", Ulong);
+ info.AddValue("ulongs", Ulongs, typeof(ulong[]));
+ info.AddValue("float", Float);
+ info.AddValue("floats", Floats, typeof(float[]));
+ info.AddValue("double", Double);
+ info.AddValue("doubles", Doubles, typeof(double[]));
+ info.AddValue("decimal", Decimal);
+ info.AddValue("decimals", Decimals, typeof(decimal[]));
+ info.AddValue("guid", Guid);
+ info.AddValue("guids", Guids, typeof(Guid[]));
+ info.AddValue("datetime", DateTime);
+ info.AddValue("datetimes", DateTimes, typeof(DateTime[]));
+ info.AddValue("string", String, typeof(string));
+ info.AddValue("strings", Strings, typeof(string[]));
+ }
+ }
+
+ [Serializable]
+ private class PrimitivesNullable : ISerializable
+ {
+ public bool GetObjectDataCalled { get; private set; }
+ public bool SerializationCtorCalled { get; private set; }
+
+ public byte? Byte { get; set; }
+ public byte?[] Bytes { get; set; }
+ public sbyte? Sbyte { get; set; }
+ public sbyte?[] Sbytes { get; set; }
+ public bool? Bool { get; set; }
+ public bool?[] Bools { get; set; }
+ public char? Char { get; set; }
+ public char?[] Chars { get; set; }
+ public short? Short { get; set; }
+ public short?[] Shorts { get; set; }
+ public ushort? Ushort { get; set; }
+ public ushort?[] Ushorts { get; set; }
+ public int? Int { get; set; }
+ public int?[] Ints { get; set; }
+ public uint? Uint { get; set; }
+ public uint?[] Uints { get; set; }
+ public long? Long { get; set; }
+ public long?[] Longs { get; set; }
+ public ulong? Ulong { get; set; }
+ public ulong?[] Ulongs { get; set; }
+ public float? Float { get; set; }
+ public float?[] Floats { get; set; }
+ public double? Double { get; set; }
+ public double?[] Doubles { get; set; }
+ public decimal? Decimal { get; set; }
+ public decimal?[] Decimals { get; set; }
+ public Guid? Guid { get; set; }
+ public Guid?[] Guids { get; set; }
+ public DateTime? DateTime { get; set; }
+ public DateTime?[] DateTimes { get; set; }
+
+ public PrimitivesNullable()
+ {
+ // No-op.
+ }
+
+ protected PrimitivesNullable(SerializationInfo info, StreamingContext context)
+ {
+ SerializationCtorCalled = true;
+
+ Byte = (byte?) info.GetValue("byte", typeof(byte?));
+ Bytes = (byte?[]) info.GetValue("bytes", typeof(byte?[]));
+
+ Sbyte = (sbyte?) info.GetValue("sbyte", typeof(sbyte?));
+ Sbytes = (sbyte?[]) info.GetValue("sbytes", typeof(sbyte?[]));
+
+ Bool = (bool?) info.GetValue("bool", typeof(bool?));
+ Bools = (bool?[]) info.GetValue("bools", typeof(bool?[]));
+
+ Char = (char?) info.GetValue("char", typeof(char?));
+ Chars = (char?[]) info.GetValue("chars", typeof(char?[]));
+
+ Short = (short?) info.GetValue("short", typeof(short?));
+ Shorts = (short?[]) info.GetValue("shorts", typeof(short?[]));
+
+ Ushort = (ushort?) info.GetValue("ushort", typeof(ushort?));
+ Ushorts = (ushort?[]) info.GetValue("ushorts", typeof(ushort?[]));
+
+ Int = (int?) info.GetValue("int", typeof(int?));
+ Ints = (int?[]) info.GetValue("ints", typeof(int?[]));
+
+ Uint = (uint?) info.GetValue("uint", typeof(uint?));
+ Uints = (uint?[]) info.GetValue("uints", typeof(uint?[]));
+
+ Long = (long?) info.GetValue("long", typeof(long?));
+ Longs = (long?[]) info.GetValue("longs", typeof(long?[]));
+
+ Ulong = (ulong?) info.GetValue("ulong", typeof(ulong?));
+ Ulongs = (ulong?[]) info.GetValue("ulongs", typeof(ulong?[]));
+
+ Float = (float?) info.GetValue("float", typeof(float?));
+ Floats = (float?[]) info.GetValue("floats", typeof(float?[]));
+
+ Double = (double?) info.GetValue("double", typeof(double?));
+ Doubles = (double?[]) info.GetValue("doubles", typeof(double?[]));
+
+ Decimal = (decimal?) info.GetValue("decimal", typeof(decimal?));
+ Decimals = (decimal?[]) info.GetValue("decimals", typeof(decimal?[]));
+
+ Guid = (Guid?) info.GetValue("guid", typeof(Guid?));
+ Guids = (Guid?[]) info.GetValue("guids", typeof(Guid?[]));
+
+ DateTime = (DateTime?) info.GetValue("datetime", typeof(DateTime?));
+ DateTimes = (DateTime?[]) info.GetValue("datetimes", typeof(DateTime?[]));
+ }
+
+ public void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ GetObjectDataCalled = true;
+
+ info.AddValue("byte", Byte, typeof(object));
+ info.AddValue("bytes", Bytes, typeof(object));
+ info.AddValue("sbyte", Sbyte, typeof(object));
+ info.AddValue("sbytes", Sbytes, typeof(object));
+ info.AddValue("bool", Bool, typeof(object));
+ info.AddValue("bools", Bools, typeof(object));
+ info.AddValue("char", Char, typeof(object));
+ info.AddValue("chars", Chars, typeof(object));
+ info.AddValue("short", Short, typeof(object));
+ info.AddValue("shorts", Shorts, typeof(object));
+ info.AddValue("ushort", Ushort, typeof(object));
+ info.AddValue("ushorts", Ushorts, typeof(object));
+ info.AddValue("int", Int, typeof(object));
+ info.AddValue("ints", Ints, typeof(object));
+ info.AddValue("uint", Uint, typeof(object));
+ info.AddValue("uints", Uints, typeof(object));
+ info.AddValue("long", Long, typeof(object));
+ info.AddValue("longs", Longs, typeof(object));
+ info.AddValue("ulong", Ulong, typeof(object));
+ info.AddValue("ulongs", Ulongs, typeof(object));
+ info.AddValue("float", Float, typeof(object));
+ info.AddValue("floats", Floats, typeof(object));
+ info.AddValue("double", Double, typeof(object));
+ info.AddValue("doubles", Doubles, typeof(object));
+ info.AddValue("decimal", Decimal, typeof(object));
+ info.AddValue("decimals", Decimals, typeof(object));
+ info.AddValue("guid", Guid, typeof(object));
+ info.AddValue("guids", Guids, typeof(object));
+ info.AddValue("datetime", DateTime, typeof(object));
+ info.AddValue("datetimes", DateTimes, typeof(object));
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/Serializable/SqlDmlTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/Serializable/SqlDmlTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/Serializable/SqlDmlTest.cs
new file mode 100644
index 0000000..b59247e
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/Serializable/SqlDmlTest.cs
@@ -0,0 +1,277 @@
+\ufeff/*
+ * 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.
+ */
+
+// ReSharper disable UnusedMember.Local
+// ReSharper disable UnusedParameter.Local
+namespace Apache.Ignite.Core.Tests.Binary.Serializable
+{
+ using System;
+ using System.IO;
+ using System.Linq;
+ using System.Runtime.Serialization;
+ using System.Text;
+ using System.Threading;
+ using Apache.Ignite.Core.Binary;
+ using Apache.Ignite.Core.Cache.Configuration;
+ using Apache.Ignite.Core.Cache.Query;
+ using Apache.Ignite.Linq;
+ using NUnit.Framework;
+
+ /// <summary>
+ /// Tests SQL and DML with Serializable types.
+ /// </summary>
+ public class SqlDmlTest
+ {
+ /** */
+ private IIgnite _ignite;
+
+ /** */
+ private StringBuilder _outSb;
+
+ /// <summary>
+ /// Sets up the test fixture.
+ /// </summary>
+ [TestFixtureSetUp]
+ public void FixtureSetUp()
+ {
+ _outSb = new StringBuilder();
+ Console.SetError(new StringWriter(_outSb));
+
+ var cfg = new IgniteConfiguration(TestUtils.GetTestConfiguration())
+ {
+ BinaryConfiguration = new BinaryConfiguration(typeof(SimpleSerializable))
+ };
+
+ _ignite = Ignition.Start(cfg);
+ }
+
+ /// <summary>
+ /// Tears down the test fixture.
+ /// </summary>
+ [TestFixtureTearDown]
+ public void FixtureTearDown()
+ {
+ Ignition.StopAll(true);
+ }
+
+ /// <summary>
+ /// Tests the simple serializable.
+ /// </summary>
+ [Test]
+ public void TestSimpleSerializable()
+ {
+ var cache = _ignite.CreateCache<int, SimpleSerializable>(
+ new CacheConfiguration("simple", new QueryEntity(typeof(int), typeof(SimpleSerializable))));
+
+ cache[1] = new SimpleSerializable
+ {
+ String = "abc"
+ };
+ cache[2] = new SimpleSerializable
+ {
+ Byte = 25,
+ Bool = true,
+ Short = 66,
+ Int = 2,
+ Long = 98,
+ Float = 2.25f,
+ Double = 1.123,
+ Decimal = 5.67m,
+ Guid = Guid.NewGuid(),
+ String = "bar2"
+ };
+
+ // Test SQL.
+ var res = cache.Query(new SqlQuery(typeof(SimpleSerializable), "where Int = 2")).GetAll().Single();
+
+ Assert.AreEqual(2, res.Key);
+ Assert.AreEqual(2, res.Value.Int);
+ Assert.AreEqual("bar2", res.Value.String);
+
+ // Test DML.
+ var guid = Guid.NewGuid();
+ var insertRes = cache.QueryFields(new SqlFieldsQuery(
+ "insert into SimpleSerializable(_key, Byte, Bool, Short, Int, Long, Float, Double, " +
+ "Decimal, Guid, String) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
+ 3, 45, true, 43, 33, 99, 4.5f, 6.7, 9.04m, guid, "bar33")).GetAll();
+
+ Assert.AreEqual(1, insertRes.Count);
+ Assert.AreEqual(1, insertRes[0][0]);
+
+ var dmlRes = cache[3];
+ Assert.AreEqual(45, dmlRes.Byte);
+ Assert.AreEqual(true, dmlRes.Bool);
+ Assert.AreEqual(43, dmlRes.Short);
+ Assert.AreEqual(33, dmlRes.Int);
+ Assert.AreEqual(99, dmlRes.Long);
+ Assert.AreEqual(4.5f, dmlRes.Float);
+ Assert.AreEqual(6.7, dmlRes.Double);
+ Assert.AreEqual(9.04m, dmlRes.Decimal);
+ Assert.AreEqual(guid, dmlRes.Guid);
+ Assert.AreEqual("bar33", dmlRes.String);
+ }
+
+ /// <summary>
+ /// Tests the .NET specific serializable.
+ /// </summary>
+ [Test]
+ public void TestDotNetSpecificSerializable()
+ {
+ var cache = _ignite.CreateCache<int, DotNetSpecificSerializable>(new CacheConfiguration("dotnet-ser",
+ new QueryEntity(typeof(int), typeof(DotNetSpecificSerializable))));
+
+ cache[1] = new DotNetSpecificSerializable(uint.MaxValue);
+ Assert.AreEqual(uint.MaxValue, cache[1].Uint);
+
+ // Test SQL.
+ var sqlRes = cache.QueryFields(new SqlFieldsQuery(
+ "select uint from DotNetSpecificSerializable where uint <> 0")).GetAll();
+
+ Assert.AreEqual(1, sqlRes.Count);
+ Assert.AreEqual(uint.MaxValue, (uint) (int) sqlRes[0][0]);
+
+ // Test LINQ.
+ var linqRes = cache.AsCacheQueryable().Select(x => x.Value.Uint).Single();
+ Assert.AreEqual(uint.MaxValue, linqRes);
+
+ // Test DML.
+ var dmlRes = cache.QueryFields(new SqlFieldsQuery(
+ "insert into DotNetSpecificSerializable(_key, uint) values (?, ?), (?, ?)",
+ 2, uint.MaxValue, 3, 88)).GetAll();
+ Assert.AreEqual(1, dmlRes.Count);
+
+ Assert.AreEqual(88, cache[3].Uint); // Works when value is in int range.
+
+ var ex = Assert.Throws<OverflowException>(() => cache.Get(2)); // Fails when out of int range.
+ Assert.AreEqual("Value was either too large or too small for a UInt32.", ex.Message);
+ }
+
+ /// <summary>
+ /// Tests the log warning.
+ /// </summary>
+ [Test]
+ public void TestLogWarning()
+ {
+ Thread.Sleep(10); // Wait for logger update.
+
+ var expected =
+ string.Format("[WARN ][main][Marshaller] Type '{0}' implements '{1}'. " +
+ "It will be written in Ignite binary format, however, " +
+ "the following limitations apply: DateTime fields would not work in SQL; " +
+ "sbyte, ushort, uint, ulong fields would not work in DML.",
+ typeof(SimpleSerializable), typeof(ISerializable));
+
+ Assert.IsTrue(_outSb.ToString().Contains(expected));
+ }
+
+ /// <summary>
+ /// Serializable with Java-compatible fields.
+ /// </summary>
+ private class SimpleSerializable : ISerializable
+ {
+ [QuerySqlField]
+ public byte Byte { get; set; }
+
+ [QuerySqlField]
+ public bool Bool { get; set; }
+
+ [QuerySqlField]
+ public short Short { get; set; }
+
+ [QuerySqlField]
+ public int Int { get; set; }
+
+ [QuerySqlField]
+ public long Long { get; set; }
+
+ [QuerySqlField]
+ public float Float { get; set; }
+
+ [QuerySqlField]
+ public double Double { get; set; }
+
+ [QuerySqlField]
+ public decimal Decimal { get; set; }
+
+ [QuerySqlField]
+ public Guid Guid { get; set; }
+
+ [QuerySqlField]
+ public string String { get; set; }
+
+ public SimpleSerializable()
+ {
+ // No-op.
+ }
+
+ public SimpleSerializable(SerializationInfo info, StreamingContext context)
+ {
+ Byte = info.GetByte("Byte");
+ Bool = info.GetBoolean("Bool");
+ Short = info.GetInt16("Short");
+ Int = info.GetInt32("Int");
+ Long = info.GetInt64("Long");
+ Float = info.GetSingle("Float");
+ Double = info.GetDouble("Double");
+ Decimal = info.GetDecimal("Decimal");
+ Guid = (Guid) info.GetValue("Guid", typeof(Guid));
+ String = info.GetString("String");
+ }
+
+ public void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ info.AddValue("Byte", Byte);
+ info.AddValue("Bool", Bool);
+ info.AddValue("Short", Short);
+ info.AddValue("Int", Int);
+ info.AddValue("Long", Long);
+ info.AddValue("Float", Float);
+ info.AddValue("Double", Double);
+ info.AddValue("Decimal", Decimal);
+ info.AddValue("Guid", Guid);
+ info.AddValue("String", String);
+ }
+ }
+
+ /// <summary>
+ /// Serializable with incompatible fields.
+ /// </summary>
+ private class DotNetSpecificSerializable : ISerializable
+ {
+ /// <summary>
+ /// Uint is not supported in Java.
+ /// </summary>
+ [QuerySqlField]
+ public uint Uint { get; set; }
+
+ public DotNetSpecificSerializable(uint u)
+ {
+ Uint = u;
+ }
+
+ public DotNetSpecificSerializable(SerializationInfo info, StreamingContext context)
+ {
+ Uint = info.GetUInt32("uint");
+ }
+
+ public void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ info.AddValue("uint", Uint);
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Affinity/AffinityFunctionTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Affinity/AffinityFunctionTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Affinity/AffinityFunctionTest.cs
index 9348449..a3e6252 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Affinity/AffinityFunctionTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Affinity/AffinityFunctionTest.cs
@@ -233,21 +233,6 @@ namespace Apache.Ignite.Core.Tests.Cache.Affinity
}
/// <summary>
- /// Tests the error on non-serializable function.
- /// </summary>
- [Test]
- public void TestNonSerializableFunction()
- {
- var ex = Assert.Throws<IgniteException>(() =>
- _ignite.CreateCache<int, int>(new CacheConfiguration("failCache")
- {
- AffinityFunction = new NonSerializableAffinityFunction()
- }));
-
- Assert.AreEqual(ex.Message, "AffinityFunction should be serializable.");
- }
-
- /// <summary>
/// Tests the exception propagation.
/// </summary>
[Test]
@@ -388,12 +373,6 @@ namespace Apache.Ignite.Core.Tests.Cache.Affinity
}
}
- private class NonSerializableAffinityFunction : SimpleAffinityFunction
- {
- // No-op.
- }
-
- [Serializable]
private class FailInGetPartitionAffinityFunction : IAffinityFunction
{
public int Partitions
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/CacheAbstractTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/CacheAbstractTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/CacheAbstractTest.cs
index f97741a..ce0441d 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/CacheAbstractTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/CacheAbstractTest.cs
@@ -232,9 +232,19 @@ namespace Apache.Ignite.Core.Tests.Cache
/// <summary>
/// Non-serializable processor.
/// </summary>
- public class NonSerializableCacheEntryProcessor : AddArgCacheEntryProcessor
+ public class NonSerializableCacheEntryProcessor : AddArgCacheEntryProcessor, IBinarizable
{
- // No-op.
+ /** <inheritdoc /> */
+ public void WriteBinary(IBinaryWriter writer)
+ {
+ throw new Exception("ExpectedException");
+ }
+
+ /** <inheritdoc /> */
+ public void ReadBinary(IBinaryReader reader)
+ {
+ throw new Exception("ExpectedException");
+ }
}
/// <summary>
@@ -269,9 +279,19 @@ namespace Apache.Ignite.Core.Tests.Cache
/// <summary>
/// Non-serializable exception.
/// </summary>
- public class NonSerializableException : Exception
+ public class NonSerializableException : Exception, IBinarizable
{
- // No-op
+ /** <inheritdoc /> */
+ public void WriteBinary(IBinaryWriter writer)
+ {
+ throw new Exception("ExpectedException");
+ }
+
+ /** <inheritdoc /> */
+ public void ReadBinary(IBinaryReader reader)
+ {
+ throw new Exception("ExpectedException");
+ }
}
/// <summary>
@@ -2356,15 +2376,7 @@ namespace Apache.Ignite.Core.Tests.Cache
TestInvoke<AddArgCacheEntryProcessor>(async);
TestInvoke<BinarizableAddArgCacheEntryProcessor>(async);
- try
- {
- TestInvoke<NonSerializableCacheEntryProcessor>(async);
- Assert.Fail();
- }
- catch (BinaryObjectException)
- {
- // Expected
- }
+ Assert.Throws<Exception>(() => TestInvoke<NonSerializableCacheEntryProcessor>(async));
}
private void TestInvoke<T>(bool async) where T: AddArgCacheEntryProcessor, new()
@@ -2396,7 +2408,7 @@ namespace Apache.Ignite.Core.Tests.Cache
AssertThrowsCacheEntryProcessorException(
() => cache.Invoke(key, new T {ThrowErrBinarizable = true}, arg));
AssertThrowsCacheEntryProcessorException(
- () => cache.Invoke(key, new T { ThrowErrNonSerializable = true }, arg), "BinaryObjectException");
+ () => cache.Invoke(key, new T { ThrowErrNonSerializable = true }, arg), "ExpectedException");
}
private static void AssertThrowsCacheEntryProcessorException(Action action, string containsText = null)
@@ -2417,7 +2429,8 @@ namespace Apache.Ignite.Core.Tests.Cache
Assert.AreEqual(AddArgCacheEntryProcessor.ExceptionText, ex.InnerException.Message);
}
else
- Assert.IsTrue(ex.ToString().Contains(containsText));
+ Assert.IsTrue(ex.ToString().Contains(containsText),
+ "Expected: " + containsText + ", actual: " + ex);
}
}
@@ -2439,16 +2452,7 @@ namespace Apache.Ignite.Core.Tests.Cache
{
TestInvokeAll<AddArgCacheEntryProcessor>(async, i);
TestInvokeAll<BinarizableAddArgCacheEntryProcessor>(async, i);
-
- try
- {
- TestInvokeAll<NonSerializableCacheEntryProcessor>(async, i);
- Assert.Fail();
- }
- catch (BinaryObjectException)
- {
- // Expected
- }
+ Assert.Throws<Exception>(() => TestInvokeAll<NonSerializableCacheEntryProcessor>(async, i));
}
}
@@ -2493,7 +2497,7 @@ namespace Apache.Ignite.Core.Tests.Cache
TestInvokeAllException(cache, entries, new T { ThrowErrBinarizable = true, ThrowOnKey = errKey },
arg, errKey);
TestInvokeAllException(cache, entries, new T { ThrowErrNonSerializable = true, ThrowOnKey = errKey },
- arg, errKey, "BinaryObjectException");
+ arg, errKey, "ExpectedException");
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheQueriesTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheQueriesTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheQueriesTest.cs
index fc47f52..d6705d4 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheQueriesTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheQueriesTest.cs
@@ -55,7 +55,6 @@ namespace Apache.Ignite.Core.Tests.Cache.Query
[TestFixtureSetUp]
public void StartGrids()
{
- TestUtils.JvmDebug = true;
TestUtils.KillProcesses();
IgniteConfiguration cfg = new IgniteConfiguration
@@ -867,8 +866,16 @@ namespace Apache.Ignite.Core.Tests.Cache.Query
/// <summary>
/// Filter that can't be serialized.
/// </summary>
- public class InvalidScanQueryFilter<TV> : ScanQueryFilter<TV>
+ public class InvalidScanQueryFilter<TV> : ScanQueryFilter<TV>, IBinarizable
{
- // No-op.
+ public void WriteBinary(IBinaryWriter writer)
+ {
+ throw new BinaryObjectException("Expected");
+ }
+
+ public void ReadBinary(IBinaryReader reader)
+ {
+ throw new BinaryObjectException("Expected");
+ }
}
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Continuous/ContinuousQueryAbstractTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Continuous/ContinuousQueryAbstractTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Continuous/ContinuousQueryAbstractTest.cs
index e890198..3c0633d 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Continuous/ContinuousQueryAbstractTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Continuous/ContinuousQueryAbstractTest.cs
@@ -15,6 +15,7 @@
* limitations under the License.
*/
+#pragma warning disable 618
namespace Apache.Ignite.Core.Tests.Cache.Query.Continuous
{
using System;
@@ -1108,9 +1109,19 @@ namespace Apache.Ignite.Core.Tests.Cache.Query.Continuous
/// <summary>
/// Filter which cannot be serialized.
/// </summary>
- public class LocalFilter : AbstractFilter<BinarizableEntry>
+ public class LocalFilter : AbstractFilter<BinarizableEntry>, IBinarizable
{
- // No-op.
+ /** <inheritDoc /> */
+ public void WriteBinary(IBinaryWriter writer)
+ {
+ throw new BinaryObjectException("Expected");
+ }
+
+ /** <inheritDoc /> */
+ public void ReadBinary(IBinaryReader reader)
+ {
+ throw new BinaryObjectException("Expected");
+ }
}
/// <summary>
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Store/CacheStoreTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Store/CacheStoreTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Store/CacheStoreTest.cs
index 4b13b9f..76241d2 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Store/CacheStoreTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Store/CacheStoreTest.cs
@@ -23,7 +23,9 @@ namespace Apache.Ignite.Core.Tests.Cache.Store
using System.Linq;
using Apache.Ignite.Core.Binary;
using Apache.Ignite.Core.Cache;
+ using Apache.Ignite.Core.Cache.Configuration;
using Apache.Ignite.Core.Cache.Store;
+ using Apache.Ignite.Core.Common;
using Apache.Ignite.Core.Impl;
using NUnit.Framework;
@@ -107,9 +109,6 @@ namespace Apache.Ignite.Core.Tests.Cache.Store
for (int i = 105; i < 110; i++)
Assert.AreEqual("val_" + i, cache.Get(i));
- // Test invalid filter
- Assert.Throws<BinaryObjectException>(() => cache.LoadCache(new InvalidCacheEntryFilter(), 100, 10));
-
// Test exception in filter
Assert.Throws<CacheStoreException>(() => cache.LoadCache(new ExceptionalEntryFilter(), 100, 10));
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Compute/ComputeApiTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Compute/ComputeApiTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Compute/ComputeApiTest.cs
index e82e238..3ef9ad0 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Compute/ComputeApiTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Compute/ComputeApiTest.cs
@@ -911,10 +911,12 @@ namespace Apache.Ignite.Core.Tests.Compute
Assert.AreEqual(1, res.GetField<int>("field"));
// This call must fail because "keepBinary" flag is reset.
- Assert.Catch(typeof(BinaryObjectException), () =>
+ var ex = Assert.Throws<BinaryObjectException>(() =>
{
compute.ExecuteJavaTask<IBinaryObject>(EchoTask, EchoTypeBinarizableJava);
});
+
+ Assert.AreEqual("Unknown pair [platformId=1, typeId=2009791293]", ex.Message);
}
/// <summary>
@@ -1386,9 +1388,17 @@ namespace Apache.Ignite.Core.Tests.Compute
}
}
- class InvalidNetSimpleJob : NetSimpleJob
+ class InvalidNetSimpleJob : NetSimpleJob, IBinarizable
{
- // No-op.
+ public void WriteBinary(IBinaryWriter writer)
+ {
+ throw new BinaryObjectException("Expected");
+ }
+
+ public void ReadBinary(IBinaryReader reader)
+ {
+ throw new BinaryObjectException("Expected");
+ }
}
[Serializable]
@@ -1460,9 +1470,17 @@ namespace Apache.Ignite.Core.Tests.Compute
}
}
- class InvalidComputeAction : ComputeAction
+ class InvalidComputeAction : ComputeAction, IBinarizable
{
- // No-op.
+ public void WriteBinary(IBinaryWriter writer)
+ {
+ throw new BinaryObjectException("Expected");
+ }
+
+ public void ReadBinary(IBinaryReader reader)
+ {
+ throw new BinaryObjectException("Expected");
+ }
}
interface IUserInterface<out T>
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Compute/IgniteExceptionTaskSelfTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Compute/IgniteExceptionTaskSelfTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Compute/IgniteExceptionTaskSelfTest.cs
index 912102c..21cd263 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Compute/IgniteExceptionTaskSelfTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Compute/IgniteExceptionTaskSelfTest.cs
@@ -88,9 +88,7 @@ namespace Apache.Ignite.Core.Tests.Compute
{
Mode = ErrorMode.MapJobNotMarshalable;
- var e = ExecuteWithError() as BinaryObjectException;
-
- Assert.IsNotNull(e);
+ Assert.IsInstanceOf<BinaryObjectException>(ExecuteWithError());
}
/// <summary>
@@ -168,13 +166,7 @@ namespace Apache.Ignite.Core.Tests.Compute
{
Mode = ErrorMode.RmtJobErrNotMarshalable;
- int res = Execute();
-
- Assert.AreEqual(1, res);
-
- Assert.AreEqual(4, JobErrs.Count);
-
- Assert.IsNotNull(JobErrs.ElementAt(0) as IgniteException);
+ Assert.Throws<SerializationException>(() => Execute());
}
/// <summary>
@@ -566,7 +558,7 @@ namespace Apache.Ignite.Core.Tests.Compute
/// <summary>
///
/// </summary>
- public class BadJob : IComputeJob<object>
+ public class BadJob : IComputeJob<object>, IBinarizable
{
[InstanceResource]
@@ -581,6 +573,18 @@ namespace Apache.Ignite.Core.Tests.Compute
{
// No-op.
}
+
+ /** <inheritDoc /> */
+ public void WriteBinary(IBinaryWriter writer)
+ {
+ throw new BinaryObjectException("Expected");
+ }
+
+ /** <inheritDoc /> */
+ public void ReadBinary(IBinaryReader reader)
+ {
+ throw new BinaryObjectException("Expected");
+ }
}
/// <summary>
@@ -621,7 +625,7 @@ namespace Apache.Ignite.Core.Tests.Compute
/// <summary>
///
/// </summary>
- public class BadJobResult
+ public class BadJobResult : IBinarizable
{
/** */
public bool Rmt;
@@ -634,6 +638,18 @@ namespace Apache.Ignite.Core.Tests.Compute
{
Rmt = rmt;
}
+
+ /** <inheritDoc /> */
+ public void WriteBinary(IBinaryWriter writer)
+ {
+ throw new BinaryObjectException("Expected");
+ }
+
+ /** <inheritDoc /> */
+ public void ReadBinary(IBinaryReader reader)
+ {
+ throw new BinaryObjectException("Expected");
+ }
}
/// <summary>
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Compute/ResourceTaskTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Compute/ResourceTaskTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Compute/ResourceTaskTest.cs
index 433b635..c693a8b 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Compute/ResourceTaskTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Compute/ResourceTaskTest.cs
@@ -21,6 +21,7 @@ namespace Apache.Ignite.Core.Tests.Compute
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
+ using Apache.Ignite.Core.Binary;
using Apache.Ignite.Core.Cluster;
using Apache.Ignite.Core.Compute;
using Apache.Ignite.Core.Resource;
@@ -158,9 +159,17 @@ namespace Apache.Ignite.Core.Tests.Compute
/// <summary>
/// Binarizable job.
/// </summary>
- public class InjectionJobBinarizable : InjectionJob
+ public class InjectionJobBinarizable : InjectionJob, IBinarizable
{
- // No-op.
+ public void WriteBinary(IBinaryWriter writer)
+ {
+ // No-op.
+ }
+
+ public void ReadBinary(IBinaryReader reader)
+ {
+ // No-op.
+ }
}
/// <summary>
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core.Tests/DeploymentTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/DeploymentTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/DeploymentTest.cs
index ab5a1a6..ece4894 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/DeploymentTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/DeploymentTest.cs
@@ -15,8 +15,6 @@
* limitations under the License.
*/
-#pragma warning disable 649
-#pragma warning disable 169
namespace Apache.Ignite.Core.Tests
{
using System;
@@ -53,15 +51,21 @@ namespace Apache.Ignite.Core.Tests
Assert.Greater(jars.Length, 3);
foreach (var jar in jars)
- // ReSharper disable once AssignNullToNotNullAttribute
- File.Copy(jar, Path.Combine(folder, Path.GetFileName(jar)), true);
+ {
+ var fileName = Path.GetFileName(jar);
+ Assert.IsNotNull(fileName);
+ File.Copy(jar, Path.Combine(folder, fileName), true);
+ }
// Build classpath
var classpath = string.Join(";", Directory.GetFiles(folder).Select(Path.GetFileName));
// Copy .NET binaries
- foreach (var asm in new[] {typeof (IgniteRunner).Assembly, typeof (Ignition).Assembly, GetType().Assembly})
+ foreach (var asm in new[] {typeof(IgniteRunner).Assembly, typeof(Ignition).Assembly, GetType().Assembly})
+ {
+ Assert.IsNotNull(asm.Location);
File.Copy(asm.Location, Path.Combine(folder, Path.GetFileName(asm.Location)));
+ }
// Copy config
var springPath = Path.GetFullPath("config\\compute\\compute-grid2.xml");
@@ -76,7 +80,6 @@ namespace Apache.Ignite.Core.Tests
"-springConfigUrl=" + springFile,
"-jvmClasspath=" + classpath,
"-J-ea",
- "-J-Xcheck:jni",
"-J-Xms512m",
"-J-Xmx512m"
});
@@ -157,6 +160,7 @@ namespace Apache.Ignite.Core.Tests
throw new InvalidOperationException();
}
+ #pragma warning disable 649
/// <summary>
/// Function that returns process path.
/// </summary>
[5/5] ignite git commit: IGNITE-2703 .NET: Dynamic type registration
Posted by pt...@apache.org.
IGNITE-2703 .NET: Dynamic type registration
* BinaryTypeConfiguration is not required anymore
* Serializable types are written in Ignite binary format
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/79bac4f8
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/79bac4f8
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/79bac4f8
Branch: refs/heads/master
Commit: 79bac4f87b15081d44e096d5bfc2c22854aad20e
Parents: 2ad2365
Author: Pavel Tupitsyn <pt...@apache.org>
Authored: Fri Mar 31 16:31:56 2017 +0300
Committer: Pavel Tupitsyn <pt...@apache.org>
Committed: Fri Mar 31 16:31:56 2017 +0300
----------------------------------------------------------------------
.../ignite/internal/MarshallerPlatformIds.java | 3 +
.../ignite/internal/binary/BinaryUtils.java | 4 +
.../platform/PlatformContextImpl.java | 10 +-
.../binary/PlatformBinaryProcessor.java | 40 +-
.../Apache.Ignite.Core.Tests.csproj | 11 +-
.../Binary/BinaryBuilderSelfTest.cs | 112 +--
.../BinaryBuilderSelfTestDynamicRegistration.cs | 40 +
.../Binary/BinaryCompactFooterInteropTest.cs | 2 +-
.../Binary/BinaryDynamicRegistrationTest.cs | 441 +++++++++++
.../Binary/BinarySelfTest.cs | 197 +++--
.../Binary/BinarySelfTestFullFooter.cs | 5 +-
.../Binary/JavaBinaryInteropTest.cs | 182 +++++
.../Serializable/AdvancedSerializationTest.cs | 228 ++++++
.../BasicSerializableObjectsTest.cs | 124 +++
.../Binary/Serializable/CallbacksTest.cs | 369 +++++++++
.../Binary/Serializable/DelegatesTest.cs | 161 ++++
.../Binary/Serializable/ObjectReferenceTests.cs | 131 ++++
.../Binary/Serializable/PrimitivesTest.cs | 754 +++++++++++++++++++
.../Binary/Serializable/SqlDmlTest.cs | 277 +++++++
.../Cache/Affinity/AffinityFunctionTest.cs | 21 -
.../Cache/CacheAbstractTest.cs | 56 +-
.../Cache/Query/CacheQueriesTest.cs | 13 +-
.../Continuous/ContinuousQueryAbstractTest.cs | 15 +-
.../Cache/Store/CacheStoreTest.cs | 5 +-
.../Compute/ComputeApiTest.cs | 28 +-
.../Compute/IgniteExceptionTaskSelfTest.cs | 40 +-
.../Compute/ResourceTaskTest.cs | 13 +-
.../Apache.Ignite.Core.Tests/DeploymentTest.cs | 16 +-
.../Examples/ExamplesTest.cs | 2 +-
.../Apache.Ignite.Core.Tests/ExecutableTest.cs | 28 +-
.../SerializationTest.cs | 240 ------
.../Services/ServiceProxyTest.cs | 40 +-
.../Apache.Ignite.Core.Tests/TestUtils.cs | 11 +
.../Apache.Ignite.Core.csproj | 7 +-
.../Cache/Configuration/CacheConfiguration.cs | 8 +-
.../Apache.Ignite.Core/IgniteConfiguration.cs | 25 +-
.../dotnet/Apache.Ignite.Core/Ignition.cs | 4 +-
.../Impl/Binary/BinarizableSerializer.cs | 5 +-
.../Impl/Binary/BinaryFullTypeDescriptor.cs | 49 +-
.../Impl/Binary/BinaryObjectBuilder.cs | 27 +-
.../Impl/Binary/BinaryObjectHeader.cs | 13 +-
.../Impl/Binary/BinaryObjectSchemaSerializer.cs | 2 +
.../Impl/Binary/BinaryProcessor.cs | 38 +-
.../Impl/Binary/BinaryReader.cs | 39 +-
.../Impl/Binary/BinaryReflectiveActions.cs | 2 +-
.../BinaryReflectiveSerializerInternal.cs | 84 ++-
.../Binary/BinarySurrogateTypeDescriptor.cs | 13 +-
.../Impl/Binary/BinarySystemHandlers.cs | 96 +--
.../Impl/Binary/BinarySystemTypeSerializer.cs | 2 +-
.../Impl/Binary/BinaryUtils.cs | 54 +-
.../Impl/Binary/BinaryWriter.cs | 242 +++---
.../Impl/Binary/DateTimeHolder.cs | 101 ---
.../Impl/Binary/DateTimeSerializer.cs | 48 --
.../Binary/DeserializationCallbackProcessor.cs | 102 +++
.../Impl/Binary/IBinarySerializerInternal.cs | 4 +-
.../Impl/Binary/IBinaryTypeDescriptor.cs | 8 +
.../Impl/Binary/Io/BinaryStreamAdapter.cs | 119 ---
.../Impl/Binary/Marshaller.cs | 248 ++++--
.../Impl/Binary/ReflectionUtils.cs | 50 ++
.../Impl/Binary/SerializableObjectHolder.cs | 96 ---
.../Impl/Binary/SerializableSerializer.cs | 656 +++++++++++++++-
.../Impl/Binary/TypeResolver.cs | 7 +
.../Impl/Binary/UserSerializerProxy.cs | 5 +-
.../Affinity/AffinityFunctionSerializer.cs | 3 -
.../Apache.Ignite.Core/Impl/Cache/CacheImpl.cs | 3 +-
.../Common/CopyOnWriteConcurrentDictionary.cs | 35 +
.../Impl/Common/DelegateConverter.cs | 90 ++-
.../Impl/Common/DelegateTypeDescriptor.cs | 3 +-
.../Impl/Common/SerializableTypeDescriptor.cs | 222 ++++++
.../dotnet/Apache.Ignite.Core/Impl/Ignite.cs | 13 +-
.../Impl/Services/ServiceProxySerializer.cs | 4 +-
.../Impl/Unmanaged/UnmanagedCallbacks.cs | 8 +-
.../NuGet/LINQPad/ComputeExample.linq | 1 -
.../NuGet/LINQPad/PutGetExample.linq | 5 +-
.../NuGet/LINQPad/QueryExample.linq | 5 +-
.../NuGet/LINQPad/QueryExample.linq | 5 +-
.../examples/Apache.Ignite.Examples/App.config | 16 +-
.../Apache.Ignite.ExamplesDll/Binary/Address.cs | 2 -
.../Compute/CharacterCountClosure.cs | 1 -
.../Datagrid/ContinuousQueryFilter.cs | 2 -
.../Datagrid/EmployeeStorePredicate.cs | 2 -
.../Messaging/RemoteOrderedListener.cs | 1 -
.../Messaging/RemoteUnorderedListener.cs | 1 -
.../Services/MapService.cs | 1 -
84 files changed, 4956 insertions(+), 1240 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/core/src/main/java/org/apache/ignite/internal/MarshallerPlatformIds.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/MarshallerPlatformIds.java b/modules/core/src/main/java/org/apache/ignite/internal/MarshallerPlatformIds.java
index 458ae49..4167f41 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/MarshallerPlatformIds.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/MarshallerPlatformIds.java
@@ -25,6 +25,9 @@ public final class MarshallerPlatformIds {
public static final byte JAVA_ID = 0;
/** */
+ public static final byte DOTNET_ID = 1;
+
+ /** */
private MarshallerPlatformIds() {
}
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryUtils.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryUtils.java
index c59b8b7..e4011a4 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryUtils.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryUtils.java
@@ -110,6 +110,10 @@ public class BinaryUtils {
/** Flag: compact footer, no field IDs. */
public static final short FLAG_COMPACT_FOOTER = 0x0020;
+ /** Flag: raw data contains .NET type information. Always 0 in Java. Keep it here for information only. */
+ @SuppressWarnings("unused")
+ public static final short FLAG_CUSTOM_DOTNET_TYPE = 0x0040;
+
/** Offset which fits into 1 byte. */
public static final int OFFSET_1 = 1;
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/PlatformContextImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/PlatformContextImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/PlatformContextImpl.java
index 10a8f74..bdcb88c 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/PlatformContextImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/PlatformContextImpl.java
@@ -430,10 +430,12 @@ public class PlatformContextImpl implements PlatformContext {
if (schema == null) {
BinaryTypeImpl meta = (BinaryTypeImpl)cacheObjProc.metadata(typeId);
- for (BinarySchema typeSchema : meta.metadata().schemas()) {
- if (schemaId == typeSchema.schemaId()) {
- schema = typeSchema;
- break;
+ if (meta != null) {
+ for (BinarySchema typeSchema : meta.metadata().schemas()) {
+ if (schemaId == typeSchema.schemaId()) {
+ schema = typeSchema;
+ break;
+ }
}
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/binary/PlatformBinaryProcessor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/binary/PlatformBinaryProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/binary/PlatformBinaryProcessor.java
index 3c00abc..8d95ac8 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/binary/PlatformBinaryProcessor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/binary/PlatformBinaryProcessor.java
@@ -18,6 +18,8 @@
package org.apache.ignite.internal.processors.platform.binary;
import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.binary.BinaryObjectException;
+import org.apache.ignite.internal.MarshallerPlatformIds;
import org.apache.ignite.internal.binary.BinaryRawReaderEx;
import org.apache.ignite.internal.binary.BinaryRawWriterEx;
import org.apache.ignite.internal.processors.platform.PlatformAbstractTarget;
@@ -39,6 +41,12 @@ public class PlatformBinaryProcessor extends PlatformAbstractTarget {
/** */
private static final int OP_GET_SCHEMA = 4;
+ /** */
+ private static final int OP_REGISTER_TYPE = 5;
+
+ /** */
+ private static final int OP_GET_TYPE = 6;
+
/**
* Constructor.
*
@@ -50,10 +58,20 @@ public class PlatformBinaryProcessor extends PlatformAbstractTarget {
/** {@inheritDoc} */
@Override public long processInStreamOutLong(int type, BinaryRawReaderEx reader) throws IgniteCheckedException {
- if (type == OP_PUT_META) {
- platformCtx.processMetadata(reader);
+ switch (type) {
+ case OP_PUT_META:
+ platformCtx.processMetadata(reader);
+
+ return TRUE;
+
+ case OP_REGISTER_TYPE: {
+ int typeId = reader.readInt();
+ String typeName = reader.readString();
- return TRUE;
+ return platformContext().kernalContext().marshallerContext()
+ .registerClassName(MarshallerPlatformIds.DOTNET_ID, typeId, typeName)
+ ? TRUE : FALSE;
+ }
}
return super.processInStreamOutLong(type, reader);
@@ -88,6 +106,22 @@ public class PlatformBinaryProcessor extends PlatformAbstractTarget {
break;
}
+ case OP_GET_TYPE: {
+ int typeId = reader.readInt();
+
+ try {
+ String typeName = platformContext().kernalContext().marshallerContext()
+ .getClassName(MarshallerPlatformIds.DOTNET_ID, typeId);
+
+ writer.writeString(typeName);
+ }
+ catch (ClassNotFoundException e) {
+ throw new BinaryObjectException(e);
+ }
+
+ break;
+ }
+
default:
super.processInStreamOutStream(type, reader, writer);
break;
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
index 1540243..27aec9c 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
@@ -69,9 +69,17 @@
</ItemGroup>
<ItemGroup>
<Compile Include="Binary\BinaryEqualityComparerTest.cs" />
+ <Compile Include="Binary\BinaryBuilderSelfTestDynamicRegistration.cs" />
<Compile Include="Binary\BinaryReaderWriterTest.cs" />
<Compile Include="Binary\IO\BinaryStreamsTest.cs" />
+ <Compile Include="Binary\JavaBinaryInteropTest.cs" />
<Compile Include="Binary\JavaTypeMappingTest.cs" />
+ <Compile Include="Binary\Serializable\CallbacksTest.cs" />
+ <Compile Include="Binary\Serializable\DelegatesTest.cs" />
+ <Compile Include="Binary\Serializable\BasicSerializableObjectsTest.cs" />
+ <Compile Include="Binary\Serializable\ObjectReferenceTests.cs" />
+ <Compile Include="Binary\Serializable\PrimitivesTest.cs" />
+ <Compile Include="Binary\Serializable\SqlDmlTest.cs" />
<Compile Include="Binary\TypeResolverTest.cs" />
<Compile Include="Cache\Affinity\AffinityKeyTest.cs" />
<Compile Include="Cache\Affinity\AffinityTopologyVersionTest.cs" />
@@ -103,6 +111,7 @@
<Compile Include="TestAppConfig.cs" />
<Compile Include="Binary\BinaryBuilderSelfTestFullFooter.cs" />
<Compile Include="Binary\BinaryCompactFooterInteropTest.cs" />
+ <Compile Include="Binary\BinaryDynamicRegistrationTest.cs" />
<Compile Include="Binary\BinarySelfTestFullFooter.cs" />
<Compile Include="Binary\BinaryStringTest.cs" />
<Compile Include="Cache\Affinity\AffinityFieldTest.cs" />
@@ -190,7 +199,7 @@
<Compile Include="ProcessExtensions.cs" />
<Compile Include="ProjectFilesTest.cs" />
<Compile Include="ReconnectTest.cs" />
- <Compile Include="SerializationTest.cs" />
+ <Compile Include="Binary\Serializable\AdvancedSerializationTest.cs" />
<Compile Include="IgniteStartStopTest.cs" />
<Compile Include="Services\ServicesTestFullFooter.cs" />
<Compile Include="TestUtils.cs" />
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinaryBuilderSelfTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinaryBuilderSelfTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinaryBuilderSelfTest.cs
index e59611b..35c7e47 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinaryBuilderSelfTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinaryBuilderSelfTest.cs
@@ -56,36 +56,7 @@ namespace Apache.Ignite.Core.Tests.Binary
{
BinaryConfiguration = new BinaryConfiguration
{
- TypeConfigurations = new List<BinaryTypeConfiguration>
- {
- new BinaryTypeConfiguration(typeof(Empty)),
- new BinaryTypeConfiguration(typeof(Primitives)),
- new BinaryTypeConfiguration(typeof(PrimitiveArrays)),
- new BinaryTypeConfiguration(typeof(StringDateGuidEnum)),
- new BinaryTypeConfiguration(typeof(WithRaw)),
- new BinaryTypeConfiguration(typeof(MetaOverwrite)),
- new BinaryTypeConfiguration(typeof(NestedOuter)),
- new BinaryTypeConfiguration(typeof(NestedInner)),
- new BinaryTypeConfiguration(typeof(MigrationOuter)),
- new BinaryTypeConfiguration(typeof(MigrationInner)),
- new BinaryTypeConfiguration(typeof(InversionOuter)),
- new BinaryTypeConfiguration(typeof(InversionInner)),
- new BinaryTypeConfiguration(typeof(CompositeOuter)),
- new BinaryTypeConfiguration(typeof(CompositeInner)),
- new BinaryTypeConfiguration(typeof(CompositeArray)),
- new BinaryTypeConfiguration(typeof(CompositeContainer)),
- new BinaryTypeConfiguration(typeof(ToBinary)),
- new BinaryTypeConfiguration(typeof(Remove)),
- new BinaryTypeConfiguration(typeof(RemoveInner)),
- new BinaryTypeConfiguration(typeof(BuilderInBuilderOuter)),
- new BinaryTypeConfiguration(typeof(BuilderInBuilderInner)),
- new BinaryTypeConfiguration(typeof(BuilderCollection)),
- new BinaryTypeConfiguration(typeof(BuilderCollectionItem)),
- new BinaryTypeConfiguration(typeof(DecimalHolder)),
- new BinaryTypeConfiguration(TypeEmpty),
- new BinaryTypeConfiguration(typeof(TestEnumRegistered)),
- new BinaryTypeConfiguration(typeof(NameMapperTestType))
- },
+ TypeConfigurations = GetTypeConfigurations(),
DefaultIdMapper = new IdMapper(),
DefaultNameMapper = new NameMapper(),
CompactFooter = GetCompactFooter()
@@ -98,6 +69,43 @@ namespace Apache.Ignite.Core.Tests.Binary
}
/// <summary>
+ /// Gets the type configurations.
+ /// </summary>
+ protected virtual ICollection<BinaryTypeConfiguration> GetTypeConfigurations()
+ {
+ return new[]
+ {
+ new BinaryTypeConfiguration(typeof(Empty)),
+ new BinaryTypeConfiguration(typeof(Primitives)),
+ new BinaryTypeConfiguration(typeof(PrimitiveArrays)),
+ new BinaryTypeConfiguration(typeof(StringDateGuidEnum)),
+ new BinaryTypeConfiguration(typeof(WithRaw)),
+ new BinaryTypeConfiguration(typeof(MetaOverwrite)),
+ new BinaryTypeConfiguration(typeof(NestedOuter)),
+ new BinaryTypeConfiguration(typeof(NestedInner)),
+ new BinaryTypeConfiguration(typeof(MigrationOuter)),
+ new BinaryTypeConfiguration(typeof(MigrationInner)),
+ new BinaryTypeConfiguration(typeof(InversionOuter)),
+ new BinaryTypeConfiguration(typeof(InversionInner)),
+ new BinaryTypeConfiguration(typeof(CompositeOuter)),
+ new BinaryTypeConfiguration(typeof(CompositeInner)),
+ new BinaryTypeConfiguration(typeof(CompositeArray)),
+ new BinaryTypeConfiguration(typeof(CompositeContainer)),
+ new BinaryTypeConfiguration(typeof(ToBinary)),
+ new BinaryTypeConfiguration(typeof(Remove)),
+ new BinaryTypeConfiguration(typeof(RemoveInner)),
+ new BinaryTypeConfiguration(typeof(BuilderInBuilderOuter)),
+ new BinaryTypeConfiguration(typeof(BuilderInBuilderInner)),
+ new BinaryTypeConfiguration(typeof(BuilderCollection)),
+ new BinaryTypeConfiguration(typeof(BuilderCollectionItem)),
+ new BinaryTypeConfiguration(typeof(DecimalHolder)),
+ new BinaryTypeConfiguration(TypeEmpty),
+ new BinaryTypeConfiguration(typeof(TestEnumRegistered)),
+ new BinaryTypeConfiguration(typeof(NameMapperTestType))
+ };
+ }
+
+ /// <summary>
/// Gets the compact footer setting.
/// </summary>
protected virtual bool GetCompactFooter()
@@ -213,7 +221,7 @@ namespace Apache.Ignite.Core.Tests.Binary
// 2. Special types.
Assert.AreEqual("a", api.ToBinary<string>("a"));
- Assert.AreEqual(date, api.ToBinary<DateTime>(date));
+ Assert.AreEqual(date, api.ToBinary<IBinaryObject>(date).Deserialize<DateTime>());
Assert.AreEqual(guid, api.ToBinary<Guid>(guid));
Assert.AreEqual(TestEnumRegistered.One, api.ToBinary<IBinaryObject>(TestEnumRegistered.One)
.Deserialize<TestEnumRegistered>());
@@ -231,7 +239,8 @@ namespace Apache.Ignite.Core.Tests.Binary
Assert.AreEqual(new[] { 'a' }, api.ToBinary<char[]>(new[] { 'a' }));
Assert.AreEqual(new[] { "a" }, api.ToBinary<string[]>(new[] { "a" }));
- Assert.AreEqual(new[] { date }, api.ToBinary<DateTime[]>(new[] { date }));
+ Assert.AreEqual(new[] {date}, api.ToBinary<IBinaryObject[]>(new[] {date})
+ .Select(x => x.Deserialize<DateTime>()));
Assert.AreEqual(new[] { guid }, api.ToBinary<Guid[]>(new[] { guid }));
Assert.AreEqual(new[] { TestEnumRegistered.One},
api.ToBinary<IBinaryObject[]>(new[] { TestEnumRegistered.One})
@@ -619,6 +628,11 @@ namespace Apache.Ignite.Core.Tests.Binary
CheckPrimitiveFields1(binObj);
+ // Rebuild unchanged.
+ binObj = binObj.ToBuilder().Build();
+
+ CheckPrimitiveFields1(binObj);
+
// Specific setter methods.
var binObj2 = _grid.GetBinary().GetBuilder(typeof(Primitives))
.SetByteField("fByte", 1)
@@ -766,6 +780,11 @@ namespace Apache.Ignite.Core.Tests.Binary
CheckPrimitiveArrayFields1(binObj);
+ // Rebuild unchanged.
+ binObj = binObj.ToBuilder().Build();
+
+ CheckPrimitiveArrayFields1(binObj);
+
// Specific setters.
var binObj2 = _grid.GetBinary().GetBuilder(typeof(PrimitiveArrays))
.SetByteArrayField("fByte", new byte[] {1})
@@ -814,7 +833,7 @@ namespace Apache.Ignite.Core.Tests.Binary
.Build();
CheckPrimitiveArrayFields2(binObj);
-
+
// Check equality.
Assert.AreEqual(binObj, binObj2);
Assert.AreEqual(binObj.GetHashCode(), binObj2.GetHashCode());
@@ -918,6 +937,11 @@ namespace Apache.Ignite.Core.Tests.Binary
CheckStringDateGuidEnum1(binObj, nDate, nGuid);
+ // Rebuild with no changes.
+ binObj = binObj.ToBuilder().Build();
+
+ CheckStringDateGuidEnum1(binObj, nDate, nGuid);
+
// Specific setters.
var binObj2 = _grid.GetBinary().GetBuilder(typeof(StringDateGuidEnum))
.SetStringField("fStr", "str")
@@ -1001,12 +1025,13 @@ namespace Apache.Ignite.Core.Tests.Binary
Assert.AreEqual(BinaryTypeNames.TypeNameArrayEnum, meta.GetFieldTypeName("fEnumArr"));
Assert.AreEqual("str", binObj.GetField<string>("fStr"));
- Assert.AreEqual(nDate, binObj.GetField<DateTime?>("fNDate"));
+ Assert.AreEqual(nDate, binObj.GetField<IBinaryObject>("fNDate").Deserialize<DateTime?>());
Assert.AreEqual(nDate, binObj.GetField<DateTime?>("fNTimestamp"));
Assert.AreEqual(nGuid, binObj.GetField<Guid?>("fNGuid"));
Assert.AreEqual(TestEnum.One, binObj.GetField<IBinaryObject>("fEnum").Deserialize<TestEnum>());
Assert.AreEqual(new[] {"str"}, binObj.GetField<string[]>("fStrArr"));
- Assert.AreEqual(new[] {nDate}, binObj.GetField<DateTime?[]>("fDateArr"));
+ Assert.AreEqual(new[] {nDate}, binObj.GetField<IBinaryObject[]>("fDateArr")
+ .Select(x => x.Deserialize<DateTime?>()));
Assert.AreEqual(new[] {nDate}, binObj.GetField<DateTime?[]>("fTimestampArr"));
Assert.AreEqual(new[] {nGuid}, binObj.GetField<Guid?[]>("fGuidArr"));
Assert.AreEqual(new[] {TestEnum.One},
@@ -1028,12 +1053,13 @@ namespace Apache.Ignite.Core.Tests.Binary
var builder = _grid.GetBinary().GetBuilder(binObj);
Assert.AreEqual("str", builder.GetField<string>("fStr"));
- Assert.AreEqual(nDate, builder.GetField<DateTime?>("fNDate"));
+ Assert.AreEqual(nDate, builder.GetField<IBinaryObjectBuilder>("fNDate").Build().Deserialize<DateTime?>());
Assert.AreEqual(nDate, builder.GetField<DateTime?>("fNTimestamp"));
Assert.AreEqual(nGuid, builder.GetField<Guid?>("fNGuid"));
Assert.AreEqual(TestEnum.One, builder.GetField<IBinaryObject>("fEnum").Deserialize<TestEnum>());
Assert.AreEqual(new[] {"str"}, builder.GetField<string[]>("fStrArr"));
- Assert.AreEqual(new[] {nDate}, builder.GetField<DateTime?[]>("fDateArr"));
+ Assert.AreEqual(new[] {nDate}, builder.GetField<IBinaryObjectBuilder[]>("fDateArr")
+ .Select(x => x.Build().Deserialize<DateTime?>()));
Assert.AreEqual(new[] {nDate}, builder.GetField<DateTime?[]>("fTimestampArr"));
Assert.AreEqual(new[] {nGuid}, builder.GetField<Guid?[]>("fGuidArr"));
Assert.AreEqual(new[] {TestEnum.One},
@@ -1043,12 +1069,13 @@ namespace Apache.Ignite.Core.Tests.Binary
binObj = builder.Build();
Assert.AreEqual("str", binObj.GetField<string>("fStr"));
- Assert.AreEqual(nDate, binObj.GetField<DateTime?>("fNDate"));
+ Assert.AreEqual(nDate, binObj.GetField<IBinaryObject>("fNDate").Deserialize<DateTime?>());
Assert.AreEqual(nDate, binObj.GetField<DateTime?>("fNTimestamp"));
Assert.AreEqual(nGuid, binObj.GetField<Guid?>("fNGuid"));
Assert.AreEqual(TestEnum.One, binObj.GetField<IBinaryObject>("fEnum").Deserialize<TestEnum>());
Assert.AreEqual(new[] {"str"}, binObj.GetField<string[]>("fStrArr"));
- Assert.AreEqual(new[] {nDate}, binObj.GetField<DateTime?[]>("fDateArr"));
+ Assert.AreEqual(new[] {nDate}, binObj.GetField<IBinaryObject[]>("fDateArr")
+ .Select(x => x.Deserialize<DateTime?>()));
Assert.AreEqual(new[] {nDate}, binObj.GetField<DateTime?[]>("fTimestampArr"));
Assert.AreEqual(new[] {nGuid}, binObj.GetField<Guid?[]>("fGuidArr"));
Assert.AreEqual(new[] { TestEnum.One },
@@ -1073,12 +1100,13 @@ namespace Apache.Ignite.Core.Tests.Binary
private static void CheckStringDateGuidEnum2(IBinaryObject binObj, DateTime? nDate, Guid? nGuid)
{
Assert.AreEqual("str2", binObj.GetField<string>("fStr"));
- Assert.AreEqual(nDate, binObj.GetField<DateTime?>("fNDate"));
+ Assert.AreEqual(nDate, binObj.GetField<IBinaryObject>("fNDate").Deserialize<DateTime?>());
Assert.AreEqual(nDate, binObj.GetField<DateTime?>("fNTimestamp"));
Assert.AreEqual(nGuid, binObj.GetField<Guid?>("fNGuid"));
Assert.AreEqual(TestEnum.Two, binObj.GetField<IBinaryObject>("fEnum").Deserialize<TestEnum>());
Assert.AreEqual(new[] { "str2" }, binObj.GetField<string[]>("fStrArr"));
- Assert.AreEqual(new[] { nDate }, binObj.GetField<DateTime?[]>("fDateArr"));
+ Assert.AreEqual(new[] {nDate}, binObj.GetField<IBinaryObject[]>("fDateArr")
+ .Select(x => x.Deserialize<DateTime?>()));
Assert.AreEqual(new[] { nDate }, binObj.GetField<DateTime?[]>("fTimestampArr"));
Assert.AreEqual(new[] { nGuid }, binObj.GetField<Guid?[]>("fGuidArr"));
Assert.AreEqual(new[] {TestEnum.Two},
@@ -1659,7 +1687,7 @@ namespace Apache.Ignite.Core.Tests.Binary
cache1[1] = new Primitives {FByte = 3};
var obj = cache2[1];
- // Rebuild with no changes
+ // Rebuild with no changes.
cache2[2] = obj.ToBuilder().Build();
Assert.AreEqual(3, cache1[2].FByte);
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinaryBuilderSelfTestDynamicRegistration.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinaryBuilderSelfTestDynamicRegistration.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinaryBuilderSelfTestDynamicRegistration.cs
new file mode 100644
index 0000000..3f37833
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinaryBuilderSelfTestDynamicRegistration.cs
@@ -0,0 +1,40 @@
+/*
+ * 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.Tests.Binary
+{
+ using System.Collections.Generic;
+ using Apache.Ignite.Core.Binary;
+
+ /// <summary>
+ /// Binary builder self test with dynamic type registration.
+ /// </summary>
+ public class BinaryBuilderSelfTestDynamicRegistration : BinaryBuilderSelfTest
+ {
+ /** <inheritdoc /> */
+ protected override ICollection<BinaryTypeConfiguration> GetTypeConfigurations()
+ {
+ // The only type to be registered is TestEnumRegistered,
+ // because unregistered enums are handled differently.
+
+ return new []
+ {
+ new BinaryTypeConfiguration(typeof(TestEnumRegistered))
+ };
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinaryCompactFooterInteropTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinaryCompactFooterInteropTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinaryCompactFooterInteropTest.cs
index 830e7f4..76ef999 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinaryCompactFooterInteropTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinaryCompactFooterInteropTest.cs
@@ -30,7 +30,7 @@ namespace Apache.Ignite.Core.Tests.Binary
public class BinaryCompactFooterInteropTest
{
/** */
- private const string PlatformSqlQueryTask = "org.apache.ignite.platform.PlatformSqlQueryTask";
+ public const string PlatformSqlQueryTask = "org.apache.ignite.platform.PlatformSqlQueryTask";
/** */
private IIgnite _grid;
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinaryDynamicRegistrationTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinaryDynamicRegistrationTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinaryDynamicRegistrationTest.cs
new file mode 100644
index 0000000..10e6e0b
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinaryDynamicRegistrationTest.cs
@@ -0,0 +1,441 @@
+\ufeff/*
+ * 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.
+ */
+
+// ReSharper disable UnusedAutoPropertyAccessor.Local
+namespace Apache.Ignite.Core.Tests.Binary
+{
+ using System;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.IO;
+ using System.Linq;
+ using Apache.Ignite.Core.Binary;
+ using Apache.Ignite.Core.Cache.Configuration;
+ using Apache.Ignite.Core.Cache.Store;
+ using Apache.Ignite.Core.Common;
+ using Apache.Ignite.Core.Compute;
+ using Apache.Ignite.Core.Impl.Binary;
+ using Apache.Ignite.Core.Impl.Common;
+ using Apache.Ignite.Core.Tests.Compute;
+ using NUnit.Framework;
+
+ /// <summary>
+ /// Tests the dynamic type registration.
+ /// </summary>
+ public class BinaryDynamicRegistrationTest
+ {
+ /// <summary>
+ /// Executes before each test.
+ /// </summary>
+ [SetUp]
+ public void SetUp()
+ {
+ ClearMarshallerWorkDir();
+ }
+
+ /// <summary>
+ /// Tests the failed registration.
+ /// </summary>
+ [Test]
+ public void TestFailedRegistration()
+ {
+ TestFailedRegistration<Foo>(false, false);
+ TestFailedRegistration<Bin>(true, false);
+ TestFailedRegistration<BinRaw>(true, true);
+ }
+
+ /// <summary>
+ /// Tests the failed registration, when we write type name after the header.
+ /// </summary>
+ private static void TestFailedRegistration<T>(bool rawStr, bool rawInt) where T : ITest, new()
+ {
+ // Disable compact footers for local mode
+ var cfg = new BinaryConfiguration {CompactFooter = false};
+
+ // Test in local mode so that MarshallerContext can't propagate type registration.
+ var bytes = new Marshaller(cfg).Marshal(new T {Int = 1, Str = "2"});
+
+ var res = new Marshaller(cfg).Unmarshal<T>(bytes);
+
+ Assert.AreEqual(1, res.Int);
+ Assert.AreEqual("2", res.Str);
+
+ // Check binary mode
+ var bin = new Marshaller(cfg).Unmarshal<IBinaryObject>(bytes, BinaryMode.ForceBinary);
+
+ if (!rawStr)
+ Assert.AreEqual("2", bin.GetField<string>("Str"));
+
+ if (!rawInt)
+ Assert.AreEqual(1, bin.GetField<int>("Int"));
+
+ res = bin.Deserialize<T>();
+
+ Assert.AreEqual(1, res.Int);
+ Assert.AreEqual("2", res.Str);
+ }
+
+ /// <summary>
+ /// Tests the store with node restart to make sure type names are persisted to disk properly.
+ /// </summary>
+ [Test]
+ public void TestStore()
+ {
+ var cfg = new IgniteConfiguration(TestUtils.GetTestConfiguration())
+ {
+ // Disable compact footers to test grid restart with persistent store
+ // (Because store operates on raw binary objects).
+ BinaryConfiguration = new BinaryConfiguration {CompactFooter = false},
+ CacheConfiguration = new[]
+ {
+ new CacheConfiguration
+ {
+ CacheStoreFactory = new StoreFactory(),
+ ReadThrough = true,
+ WriteThrough = true
+ }
+ }
+ };
+
+ using (var ignite = Ignition.Start(TestUtils.GetTestConfiguration()))
+ {
+ // Put through dynamically started cache
+ var dynCache = ignite.CreateCache<int, Foo>(new CacheConfiguration("dynCache")
+ {
+ CacheStoreFactory = new StoreFactory(),
+ ReadThrough = true,
+ WriteThrough = true
+ });
+ dynCache[2] = new Foo { Str = "test2", Int = 3 };
+
+ // Start another server node so that store is initialized there
+ using (var ignite2 = Ignition.Start(new IgniteConfiguration(TestUtils.GetTestConfiguration())
+ {
+ IgniteInstanceName = "grid2"
+ }))
+ {
+ var dynCache2 = ignite2.GetCache<int, Foo>(dynCache.Name);
+
+ Assert.AreEqual("test2", dynCache2[2].Str);
+ Assert.AreEqual(3, dynCache2[2].Int);
+ }
+ }
+
+ using (var ignite = Ignition.Start(cfg))
+ {
+ // Put through statically started cache
+ var staticCache = ignite.GetCache<int, Foo>(null);
+ staticCache[1] = new Foo {Str = "test", Int = 2};
+ }
+
+ using (var ignite = Ignition.Start(cfg))
+ {
+ var foo = ignite.GetCache<int, Foo>(null)[1];
+ var foo2 = ignite.GetCache<int, Foo>(null)[2];
+
+ Assert.AreEqual("test", foo.Str);
+ Assert.AreEqual(2, foo.Int);
+
+ Assert.AreEqual("test2", foo2.Str);
+ Assert.AreEqual(3, foo2.Int);
+
+ // Client node
+ using (var igniteClient = Ignition.Start(new IgniteConfiguration(cfg)
+ {
+ ClientMode = true,
+ IgniteInstanceName = "grid2"
+ }))
+ {
+ var fooClient = igniteClient.GetCache<int, Foo>(null)[1];
+ var fooClient2 = igniteClient.GetCache<int, Foo>(null)[2];
+
+ Assert.AreEqual("test", fooClient.Str);
+ Assert.AreEqual(2, fooClient.Int);
+
+ Assert.AreEqual("test2", fooClient2.Str);
+ Assert.AreEqual(3, fooClient2.Int);
+ }
+ }
+
+ // Delete directory and check that store no longer works
+ ClearMarshallerWorkDir();
+
+ using (var ignite = Ignition.Start(cfg))
+ {
+ var ex = Assert.Throws<BinaryObjectException>(() => ignite.GetCache<int, Foo>(null).Get(1));
+
+ Assert.IsTrue(ex.Message.Contains("Unknown pair"));
+ }
+ }
+
+ /// <summary>
+ /// Tests the store factory property propagation.
+ /// </summary>
+ [Test]
+ public void TestStoreFactory()
+ {
+ var cfg = new IgniteConfiguration(TestUtils.GetTestConfiguration())
+ {
+ CacheConfiguration = new[]
+ {
+ new CacheConfiguration
+ {
+ CacheStoreFactory = new StoreFactory {StringProp = "test", IntProp = 9},
+ ReadThrough = true,
+ WriteThrough = true
+ }
+ }
+ };
+
+ using (Ignition.Start(cfg))
+ {
+ var storeFactory = StoreFactory.LastInstance;
+
+ Assert.AreEqual("test", storeFactory.StringProp);
+ Assert.AreEqual(9, storeFactory.IntProp);
+ }
+ }
+
+ /// <summary>
+ /// Tests the single grid scenario.
+ /// </summary>
+ [Test]
+ public void TestSingleGrid()
+ {
+ using (var ignite = Ignition.Start(TestUtils.GetTestConfiguration()))
+ {
+ Test(ignite, ignite);
+ }
+ }
+
+ /// <summary>
+ /// Tests the two grid scenario.
+ /// </summary>
+ [Test]
+ public void TestTwoGrids([Values(false, true)] bool clientMode)
+ {
+ using (var ignite1 = Ignition.Start(TestUtils.GetTestConfiguration()))
+ {
+ using (var ignite2 = Ignition.Start(new IgniteConfiguration(TestUtils.GetTestConfiguration())
+ {
+ IgniteInstanceName = "grid2",
+ ClientMode = clientMode
+ }))
+ {
+ Test(ignite1, ignite2);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Tests interop scenario: Java and .NET exchange an object with the same type id,
+ /// but marshaller cache contains different entries for different platforms for the same id.
+ /// </summary>
+ [Test]
+ public void TestJavaInterop()
+ {
+ using (var ignite = Ignition.Start(TestUtils.GetTestConfiguration()))
+ {
+ var cacheCfg = new CacheConfiguration(null, new QueryEntity(typeof(PlatformComputeBinarizable))
+ {
+ Fields = new[] {new QueryField("Field", typeof(int))}
+ });
+
+ var cache = ignite.CreateCache<int, object>(cacheCfg);
+
+ // Force dynamic registration for .NET
+ cache.Put(1, new PlatformComputeBinarizable {Field = 7});
+
+ // Run Java code that will also perform dynamic registration
+ var fromJava = ignite.GetCompute().ExecuteJavaTask<PlatformComputeBinarizable>(ComputeApiTest.EchoTask,
+ ComputeApiTest.EchoTypeBinarizable);
+
+ // Check that objects are compatible
+ Assert.AreEqual(1, fromJava.Field);
+
+ // Check that Java can read what .NET has put
+ var qryRes = ignite.GetCompute().ExecuteJavaTask<IList>(
+ BinaryCompactFooterInteropTest.PlatformSqlQueryTask, "Field < 10");
+
+ Assert.AreEqual(7, qryRes.OfType<PlatformComputeBinarizable>().Single().Field);
+ }
+ }
+
+ /// <summary>
+ /// Tests the type registration.
+ /// </summary>
+ private static void Test(IIgnite ignite1, IIgnite ignite2)
+ {
+ const string cacheName = "cache";
+
+ // Put on one grid.
+ var cache1 = ignite1.CreateCache<int, object>(cacheName);
+ cache1[1] = new Foo {Int = 1, Str = "1"};
+ cache1[2] = ignite1.GetBinary().GetBuilder(typeof (Bar)).SetField("Int", 5).SetField("Str", "s").Build();
+
+ // Get on another grid.
+ var cache2 = ignite2.GetCache<int, Foo>(cacheName);
+ var foo = cache2[1];
+
+ Assert.AreEqual(1, foo.Int);
+ Assert.AreEqual("1", foo.Str);
+
+ var bar = cache2.WithKeepBinary<int, IBinaryObject>()[2];
+
+ Assert.AreEqual("s", bar.GetField<string>("Str"));
+ Assert.AreEqual(5, bar.GetField<int>("Int"));
+
+ var bar0 = bar.Deserialize<Bar>();
+
+ Assert.AreEqual("s", bar0.Str);
+ Assert.AreEqual(5, bar0.Int);
+
+ // Test compute.
+ var serverNodeCount = ignite1.GetCluster().ForServers().GetNodes().Count;
+
+ var res = ignite1.GetCompute().Broadcast(new CompFn<DateTime>(() => DateTime.Now));
+ Assert.AreEqual(serverNodeCount, res.Count);
+
+ // Variable capture.
+ var res2 = ignite1.GetCompute().Broadcast(new CompFn<string>(() => bar0.Str));
+ Assert.AreEqual(Enumerable.Repeat(bar0.Str, serverNodeCount), res2);
+ }
+
+ /// <summary>
+ /// Clears the marshaller work dir.
+ /// </summary>
+ private static void ClearMarshallerWorkDir()
+ {
+ // Delete all *.classname files within IGNITE_HOME
+ var home = IgniteHome.Resolve(null);
+
+ var files = Directory.GetFiles(home, "*.classname*", SearchOption.AllDirectories);
+
+ files.ToList().ForEach(File.Delete);
+ }
+
+ private interface ITest
+ {
+ int Int { get; set; }
+ string Str { get; set; }
+ }
+
+ private class Foo : ITest
+ {
+ public int Int { get; set; }
+ public string Str { get; set; }
+ }
+
+ private class Bar : ITest
+ {
+ public int Int { get; set; }
+ public string Str { get; set; }
+ }
+
+ private class Bin : IBinarizable, ITest
+ {
+ public int Int { get; set; }
+ public string Str { get; set; }
+
+ public void WriteBinary(IBinaryWriter writer)
+ {
+ writer.WriteInt("Int", Int);
+ writer.GetRawWriter().WriteString(Str);
+ }
+
+ public void ReadBinary(IBinaryReader reader)
+ {
+ Int = reader.ReadInt("Int");
+ Str = reader.GetRawReader().ReadString();
+ }
+ }
+
+ private class BinRaw : IBinarizable, ITest
+ {
+ public int Int { get; set; }
+ public string Str { get; set; }
+
+ public void WriteBinary(IBinaryWriter writer)
+ {
+ var w = writer.GetRawWriter();
+
+ w.WriteInt(Int);
+ w.WriteString(Str);
+ }
+
+ public void ReadBinary(IBinaryReader reader)
+ {
+ var r = reader.GetRawReader();
+
+ Int = r.ReadInt();
+ Str = r.ReadString();
+ }
+ }
+
+ [Serializable]
+ private class StoreFactory : IFactory<ICacheStore>
+ {
+ public string StringProp { get; set; }
+
+ public int IntProp { get; set; }
+
+ public static StoreFactory LastInstance { get; set; }
+
+ public ICacheStore CreateInstance()
+ {
+ LastInstance = this;
+ return new CacheStore();
+ }
+ }
+
+ private class CacheStore : CacheStoreAdapter<object, object>
+ {
+ private static readonly Dictionary<object, object> Dict = new Dictionary<object, object>();
+
+ public override object Load(object key)
+ {
+ object res;
+ return Dict.TryGetValue(key, out res) ? res : null;
+ }
+
+ public override void Write(object key, object val)
+ {
+ Dict[key] = val;
+ }
+
+ public override void Delete(object key)
+ {
+ Dict.Remove(key);
+ }
+ }
+
+ private class CompFn<T> : IComputeFunc<T>
+ {
+ private readonly Func<T> _func;
+
+ public CompFn(Func<T> func)
+ {
+ _func = func;
+ }
+
+ public T Invoke()
+ {
+ return _func();
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/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 70226e6..eb2751e 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinarySelfTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinarySelfTest.cs
@@ -63,16 +63,16 @@ namespace Apache.Ignite.Core.Tests.Binary
[TestFixtureSetUp]
public void BeforeTest()
{
- _marsh = new Marshaller(GetBinaryConfiguration());
+ _marsh = new Marshaller(new BinaryConfiguration{CompactFooter = GetCompactFooter()});
}
/// <summary>
/// Gets the binary configuration.
/// </summary>
/// <returns></returns>
- protected virtual BinaryConfiguration GetBinaryConfiguration()
+ protected virtual bool GetCompactFooter()
{
- return new BinaryConfiguration { CompactFooter = true };
+ return true;
}
/**
@@ -691,7 +691,8 @@ namespace Apache.Ignite.Core.Tests.Binary
{
new BinaryTypeConfiguration(typeof (PrimitiveFieldType)),
new BinaryTypeConfiguration(typeof (GenericCollectionsType<PrimitiveFieldType, SerializableObject>))
- }
+ },
+ CompactFooter = GetCompactFooter()
});
var obj = new GenericCollectionsType<PrimitiveFieldType, SerializableObject>
@@ -721,6 +722,52 @@ namespace Apache.Ignite.Core.Tests.Binary
CollectionAssert.AreEquivalent(obj.Objects, result.Objects);
}
+ /// <summary>
+ /// Tests the circular reference handling with List.
+ /// </summary>
+ [Test]
+ public void TestListCircularReference()
+ {
+ var list1 = new List<object> {1};
+ var list2 = new List<object> {2};
+
+ list1.Add(list2);
+ list2.Add(list1);
+
+ var data = _marsh.Marshal(list1);
+
+ var resList1 = _marsh.Unmarshal<List<object>>(data);
+ Assert.AreEqual(1, resList1[0]);
+
+ var resList2 = (List<object>) resList1[1];
+ Assert.AreEqual(2, resList2[0]);
+ Assert.AreEqual(resList1, resList2[1]);
+ }
+
+ /// <summary>
+ /// Tests the circular reference handling with Dictionary.
+ /// This test checks proper handle support in combination with OnDeserialization callback,
+ /// which has to be called after entire graph is deserialized.
+ /// </summary>
+ [Test]
+ public void TestDictionaryCircularReference()
+ {
+ var dict1 = new Dictionary<object, object> {{0, 1}};
+ var dict2 = new Dictionary<object, object> {{0, 2}};
+
+ dict1[1] = dict2;
+ dict2[1] = dict1;
+
+ var data = _marsh.Marshal(dict1);
+
+ var resDict1 = _marsh.Unmarshal<Dictionary<object, object>>(data);
+ Assert.AreEqual(1, resDict1[0]);
+
+ var resDict2 = (Dictionary<object, object>) resDict1[1];
+ Assert.AreEqual(2, resDict2[0]);
+ Assert.AreEqual(resDict1, resDict2[1]);
+ }
+
/**
* <summary>Check property read.</summary>
*/
@@ -778,7 +825,8 @@ namespace Apache.Ignite.Core.Tests.Binary
{
Serializer = serializer
}
- }
+ },
+ CompactFooter = GetCompactFooter()
});
// Use utc date fields because reflective serializer writes [QuerySqlField] fields as timestamp
@@ -791,20 +839,17 @@ namespace Apache.Ignite.Core.Tests.Binary
CheckPrimitiveFields(marsh, obj);
}
- /**
- * <summary>Check write of primitive fields through binary interface.</summary>
- */
+ /// <summary>
+ /// Check write of primitive fields through binary interface.
+ /// </summary>
[Test]
public void TestPrimitiveFieldsBinary()
{
- ICollection<BinaryTypeConfiguration> typeCfgs =
- new List<BinaryTypeConfiguration>();
-
- typeCfgs.Add(new BinaryTypeConfiguration(typeof(PrimitiveFieldBinaryType)));
-
- BinaryConfiguration cfg = new BinaryConfiguration();
-
- cfg.TypeConfigurations = typeCfgs;
+ var cfg = new BinaryConfiguration
+ {
+ TypeConfigurations = new[] { new BinaryTypeConfiguration(typeof(PrimitiveFieldBinaryType)) },
+ CompactFooter = GetCompactFooter()
+ };
Marshaller marsh = new Marshaller(cfg);
@@ -813,44 +858,41 @@ namespace Apache.Ignite.Core.Tests.Binary
CheckPrimitiveFields(marsh, obj);
}
- /**
- * <summary>Check write of primitive fields through binary interface.</summary>
- */
+ /// <summary>
+ /// Check write of primitive fields through binary interface.
+ /// </summary>
[Test]
public void TestPrimitiveFieldsRawBinary()
{
- ICollection<BinaryTypeConfiguration> typeCfgs =
- new List<BinaryTypeConfiguration>();
-
- typeCfgs.Add(new BinaryTypeConfiguration(typeof(PrimitiveFieldRawBinaryType)));
-
- BinaryConfiguration cfg = new BinaryConfiguration();
-
- cfg.TypeConfigurations = typeCfgs;
-
- Marshaller marsh = new Marshaller(cfg);
+ var marsh = new Marshaller(new BinaryConfiguration
+ {
+ TypeConfigurations = new[] { new BinaryTypeConfiguration(typeof(PrimitiveFieldRawBinaryType)) },
+ CompactFooter = GetCompactFooter()
+ });
- PrimitiveFieldRawBinaryType obj = new PrimitiveFieldRawBinaryType();
+ var obj = new PrimitiveFieldRawBinaryType();
CheckPrimitiveFields(marsh, obj);
}
- /**
- * <summary>Check write of primitive fields through binary interface.</summary>
- */
+ /// <summary>
+ /// Check write of primitive fields through binary interface.
+ /// </summary>
[Test]
public void TestPrimitiveFieldsSerializer()
{
- var typeCfgs = new List<BinaryTypeConfiguration>
+ var cfg = new BinaryConfiguration
{
- new BinaryTypeConfiguration(typeof (PrimitiveFieldType))
+ TypeConfigurations = new[]
{
- Serializer = new PrimitiveFieldsSerializer()
- }
+ new BinaryTypeConfiguration(typeof(PrimitiveFieldType))
+ {
+ Serializer = new PrimitiveFieldsSerializer(),
+ }
+ },
+ CompactFooter = GetCompactFooter()
};
- BinaryConfiguration cfg = new BinaryConfiguration {TypeConfigurations = typeCfgs};
-
Marshaller marsh = new Marshaller(cfg);
PrimitiveFieldType obj = new PrimitiveFieldType();
@@ -909,31 +951,25 @@ namespace Apache.Ignite.Core.Tests.Binary
Assert.AreEqual(obj2.RawValArr, portObj.Deserialize<DecimalMarshalAware>().RawValArr);
}
- /**
- * <summary>Check write of primitive fields through raw serializer.</summary>
- */
+ /// <summary>
+ /// Check write of primitive fields through raw serializer.
+ /// </summary>
[Test]
public void TestPrimitiveFieldsRawSerializer()
{
- ICollection<BinaryTypeConfiguration> typeCfgs =
- new List<BinaryTypeConfiguration>();
-
- BinaryTypeConfiguration typeCfg =
- new BinaryTypeConfiguration(typeof(PrimitiveFieldType));
-
- typeCfg.Serializer = new PrimitiveFieldsRawSerializer();
-
- typeCfgs.Add(typeCfg);
-
- BinaryConfiguration cfg = new BinaryConfiguration();
-
- cfg.TypeConfigurations = typeCfgs;
-
- Marshaller marsh = new Marshaller(cfg);
-
- PrimitiveFieldType obj = new PrimitiveFieldType();
+ Marshaller marsh = new Marshaller(new BinaryConfiguration
+ {
+ TypeConfigurations = new[]
+ {
+ new BinaryTypeConfiguration(typeof(PrimitiveFieldType))
+ {
+ Serializer = new PrimitiveFieldsRawSerializer()
+ }
+ },
+ CompactFooter = GetCompactFooter()
+ });
- CheckPrimitiveFields(marsh, obj);
+ CheckPrimitiveFields(marsh, new PrimitiveFieldType());
}
private void CheckPrimitiveFields(Marshaller marsh, PrimitiveFieldType obj)
@@ -941,7 +977,7 @@ namespace Apache.Ignite.Core.Tests.Binary
CheckPrimitiveFieldsSerialization(marsh, obj);
}
- private void CheckPrimitiveFieldsSerialization(Marshaller marsh, PrimitiveFieldType obj)
+ private static void CheckPrimitiveFieldsSerialization(Marshaller marsh, PrimitiveFieldType obj)
{
byte[] bytes = marsh.Marshal(obj);
@@ -1029,7 +1065,8 @@ namespace Apache.Ignite.Core.Tests.Binary
{
Serializer = new BinaryReflectiveSerializer {RawMode = raw}
}
- }
+ },
+ CompactFooter = GetCompactFooter()
});
var obj = new CollectionsType
@@ -1239,9 +1276,7 @@ namespace Apache.Ignite.Core.Tests.Binary
{
var reader = new BinaryReader(marsh, new BinaryHeapStream(bytes), BinaryMode.ForceBinary, null);
- reader.DetachNext();
-
- outerObj = reader.Deserialize<IBinaryObject>();
+ outerObj = reader.DetachNext().Deserialize<IBinaryObject>();
}
else
outerObj = marsh.Unmarshal<IBinaryObject>(bytes, BinaryMode.ForceBinary);
@@ -1272,7 +1307,8 @@ namespace Apache.Ignite.Core.Tests.Binary
TypeConfigurations = new[]
{
new BinaryTypeConfiguration(typeof (HandleCollection))
- }
+ },
+ CompactFooter = GetCompactFooter()
});
// Collection in collection dependency loop
@@ -1441,8 +1477,10 @@ namespace Apache.Ignite.Core.Tests.Binary
Assert.AreEqual(guidArr, portObj.GetField<Guid[]>("guidArr"));
Assert.AreEqual(nGuidArr, portObj.GetField<Guid?[]>("nGuidArr"));
- Assert.AreEqual(dateArr, portObj.GetField<DateTime[]>("dateArr"));
- Assert.AreEqual(nDateArr, portObj.GetField<DateTime?[]>("nDateArr"));
+ Assert.AreEqual(dateArr, portObj.GetField<IBinaryObject[]>("dateArr")
+ .Select(x => x.Deserialize<DateTime>()));
+ Assert.AreEqual(nDateArr, portObj.GetField<IBinaryObject[]>("nDateArr")
+ .Select(x => x.Deserialize<DateTime?>()));
obj1 = portObj.Deserialize<SpecialArray>();
@@ -1452,12 +1490,13 @@ namespace Apache.Ignite.Core.Tests.Binary
Assert.AreEqual(nDateArr, obj1.NDateArr);
// Use special with IGridbinaryMarshalAware.
- SpecialArrayMarshalAware obj2 = new SpecialArrayMarshalAware();
-
- obj2.GuidArr = guidArr;
- obj2.NGuidArr = nGuidArr;
- obj2.DateArr = dateArr;
- obj2.NDateArr = nDateArr;
+ SpecialArrayMarshalAware obj2 = new SpecialArrayMarshalAware
+ {
+ GuidArr = guidArr,
+ NGuidArr = nGuidArr,
+ DateArr = dateArr,
+ NDateArr = nDateArr
+ };
bytes = marsh.Marshal(obj2);
@@ -1465,8 +1504,8 @@ namespace Apache.Ignite.Core.Tests.Binary
Assert.AreEqual(guidArr, portObj.GetField<Guid[]>("a"));
Assert.AreEqual(nGuidArr, portObj.GetField<Guid?[]>("b"));
- Assert.AreEqual(dateArr, portObj.GetField<DateTime[]>("c"));
- Assert.AreEqual(nDateArr, portObj.GetField<DateTime?[]>("d"));
+ Assert.AreEqual(dateArr, portObj.GetField<IBinaryObject[]>("c").Select(x => x.Deserialize<DateTime>()));
+ Assert.AreEqual(nDateArr, portObj.GetField<IBinaryObject[]>("d").Select(x => x.Deserialize<DateTime?>()));
obj2 = portObj.Deserialize<SpecialArrayMarshalAware>();
@@ -1523,7 +1562,7 @@ namespace Apache.Ignite.Core.Tests.Binary
[Test]
public void TestCompactFooterSetting()
{
- Assert.AreEqual(GetBinaryConfiguration().CompactFooter, _marsh.CompactFooter);
+ Assert.AreEqual(GetCompactFooter(), _marsh.CompactFooter);
}
private static void CheckKeepSerialized(BinaryConfiguration cfg, bool expKeep)
@@ -1842,8 +1881,8 @@ namespace Apache.Ignite.Core.Tests.Binary
PString = "abc";
PGuid = Guid.NewGuid();
PnGuid = Guid.NewGuid();
- PDate = DateTime.Now;
- PnDate = DateTime.Now;
+ PDate = DateTime.UtcNow;
+ PnDate = DateTime.UtcNow;
IgniteGuid = new IgniteGuid(Guid.NewGuid(), 123);
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinarySelfTestFullFooter.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinarySelfTestFullFooter.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinarySelfTestFullFooter.cs
index 06e43e1..72228cf 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinarySelfTestFullFooter.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinarySelfTestFullFooter.cs
@@ -17,7 +17,6 @@
namespace Apache.Ignite.Core.Tests.Binary
{
- using Apache.Ignite.Core.Binary;
using NUnit.Framework;
/// <summary>
@@ -27,9 +26,9 @@ namespace Apache.Ignite.Core.Tests.Binary
public class BinarySelfTestFullFooter : BinarySelfTest
{
/** <inheritdoc /> */
- protected override BinaryConfiguration GetBinaryConfiguration()
+ protected override bool GetCompactFooter()
{
- return new BinaryConfiguration {CompactFooter = false};
+ return false;
}
}
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/JavaBinaryInteropTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/JavaBinaryInteropTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/JavaBinaryInteropTest.cs
new file mode 100644
index 0000000..9af5c35
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/JavaBinaryInteropTest.cs
@@ -0,0 +1,182 @@
+\ufeff/*
+ * 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.Tests.Binary
+{
+ using System;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Linq;
+ using NUnit.Framework;
+
+ /// <summary>
+ /// Tests binary type interoperability between .NET and Java code.
+ /// </summary>
+ public class JavaBinaryInteropTest
+ {
+ /// <summary>
+ /// Tests that all kinds of values from .NET can be handled properly on Java side.
+ /// </summary>
+ [Test]
+ public void TestValueRoundtrip()
+ {
+ using (var ignite = Ignition.Start(TestUtils.GetTestConfiguration()))
+ {
+ ignite.CreateCache<int, object>((string) null);
+
+ // Basic types.
+ // Types which map directly to Java are returned properly when retrieved as object.
+ // Non-directly mapped types are returned as their counterpart.
+ CheckValueCaching((char) 128);
+ CheckValueCaching((byte) 255);
+ CheckValueCaching((sbyte) -10, false);
+ CheckValueCaching((short) -32000);
+ CheckValueCaching((ushort) 65350, false);
+ CheckValueCaching(int.MinValue);
+ CheckValueCaching(uint.MaxValue, false);
+ CheckValueCaching(long.MinValue);
+ CheckValueCaching(ulong.MaxValue, false);
+
+ CheckValueCaching((float) 1.1);
+ CheckValueCaching(2.2);
+
+ CheckValueCaching((decimal) 3.3, asArray: false);
+ CheckValueCaching(Guid.NewGuid(), asArray: false);
+ CheckValueCaching(DateTime.Now, asArray: false);
+
+ CheckValueCaching("foobar");
+
+ // Special arrays.
+ CheckValueCaching(new[] {Guid.Empty, Guid.NewGuid()}, false);
+ CheckValueCaching(new Guid?[] {Guid.Empty, Guid.NewGuid()});
+
+ CheckValueCaching(new[] {1.2m, -3.4m}, false);
+ CheckValueCaching(new decimal?[] {1.2m, -3.4m});
+
+ CheckValueCaching(new[] {DateTime.Now}, false);
+
+ // Custom types.
+ CheckValueCaching(new Foo {X = 10}, asArray: false);
+ CheckValueCaching(new Bar {X = 20}, asArray: false);
+
+ // Collections.
+ CheckValueCaching(new List<Foo>(GetFoo()));
+ CheckValueCaching(new List<Bar>(GetBar()));
+
+ CheckValueCaching(new HashSet<Foo>(GetFoo()));
+ CheckValueCaching(new HashSet<Bar>(GetBar()));
+
+ CheckValueCaching(GetFoo().ToDictionary(x => x.X, x => x));
+ CheckValueCaching(GetBar().ToDictionary(x => x.X, x => x));
+
+ // Custom type arrays.
+ // Array type is lost, because in binary mode on Java side we receive the value as Object[].
+ CheckValueCaching(new[] {new Foo {X = -1}, new Foo {X = 1}}, false);
+ CheckValueCaching(new[] {new Bar {X = -10}, new Bar {X = 10}}, false);
+ }
+ }
+
+ /// <summary>
+ /// Checks caching of a value with generic cache.
+ /// </summary>
+ private static void CheckValueCaching<T>(T val, bool asObject = true, bool asArray = true)
+ {
+ var cache = Ignition.GetIgnite(null).GetCache<int, T>(null);
+
+ cache[1] = val;
+ Assert.AreEqual(val, cache[1]);
+
+ if (asObject)
+ {
+ CheckValueCachingAsObject(val);
+ }
+
+ // Array of T
+ if (asArray && !(val is IEnumerable))
+ {
+ CheckValueCaching(new[] {val}, asObject, false);
+ }
+ }
+
+ /// <summary>
+ /// Checks caching of a value with object cache.
+ /// </summary>
+ private static void CheckValueCachingAsObject<T>(T val)
+ {
+ var cache = Ignition.GetIgnite(null).GetCache<int, object>(null);
+
+ cache[1] = val;
+ Assert.AreEqual(val, (T) cache[1]);
+ }
+
+ /// <summary>
+ /// Gets Foo collection.
+ /// </summary>
+ private static IEnumerable<Foo> GetFoo()
+ {
+ return Enumerable.Range(-50, 100).Select(x => new Foo {X = x});
+ }
+
+ /// <summary>
+ /// Gets Bar collection.
+ /// </summary>
+ private static IEnumerable<Bar> GetBar()
+ {
+ return Enumerable.Range(-50, 100).Select(x => new Bar {X = x});
+ }
+
+ /// <summary>
+ /// Test custom class.
+ /// </summary>
+ private class Foo
+ {
+ public int X { get; set; }
+
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj)) return false;
+ if (ReferenceEquals(this, obj)) return true;
+ if (obj.GetType() != GetType()) return false;
+ return X == ((Foo) obj).X;
+ }
+
+ public override int GetHashCode()
+ {
+ return X;
+ }
+ }
+
+ /// <summary>
+ /// Test custom struct.
+ /// </summary>
+ private struct Bar
+ {
+ public int X { get; set; }
+
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj)) return false;
+ return obj is Bar && X == ((Bar) obj).X;
+ }
+
+ public override int GetHashCode()
+ {
+ return X;
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/Serializable/AdvancedSerializationTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/Serializable/AdvancedSerializationTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/Serializable/AdvancedSerializationTest.cs
new file mode 100644
index 0000000..c96d111
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/Serializable/AdvancedSerializationTest.cs
@@ -0,0 +1,228 @@
+/*
+ * 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.Tests.Binary.Serializable
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Reflection;
+ using System.Reflection.Emit;
+ using System.Runtime.Serialization;
+ using System.Xml;
+ using Apache.Ignite.Core.Cluster;
+ using Apache.Ignite.Core.Compute;
+ using NUnit.Framework;
+
+ /// <summary>
+ /// Tests additional [Serializable] scenarios.
+ /// </summary>
+ public class AdvancedSerializationTest
+ {
+ /// <summary>
+ /// Set up routine.
+ /// </summary>
+ [TestFixtureSetUp]
+ public void SetUp()
+ {
+ Ignition.Start(TestUtils.GetTestConfiguration());
+ }
+
+ /// <summary>
+ /// Tear down routine.
+ /// </summary>
+ [TestFixtureTearDown]
+ public void TearDown()
+ {
+ Ignition.StopAll(true);
+ }
+
+ /// <summary>
+ /// Test complex file serialization.
+ /// </summary>
+ [Test]
+ public void TestSerializableXmlDoc()
+ {
+ var grid = Ignition.GetIgnite(null);
+ var cache = grid.GetOrCreateCache<int, SerializableXmlDoc>("cache");
+
+ var doc = new SerializableXmlDoc();
+
+ doc.LoadXml("<document><test1>val</test1><test2 attr=\"x\" /></document>");
+
+ for (var i = 0; i < 50; i++)
+ {
+ // Test cache
+ cache.Put(i, doc);
+
+ var resultDoc = cache.Get(i);
+
+ Assert.AreEqual(doc.OuterXml, resultDoc.OuterXml);
+
+ // Test task with document arg
+ CheckTask(grid, doc);
+ }
+ }
+
+ /// <summary>
+ /// Checks task execution.
+ /// </summary>
+ /// <param name="grid">Grid.</param>
+ /// <param name="arg">Task arg.</param>
+ private static void CheckTask(IIgnite grid, object arg)
+ {
+ var jobResult = grid.GetCompute().Execute(new CombineStringsTask(), arg);
+
+ var nodeCount = grid.GetCluster().GetNodes().Count;
+
+ var expectedRes =
+ CombineStringsTask.CombineStrings(Enumerable.Range(0, nodeCount).Select(x => arg.ToString()));
+
+ Assert.AreEqual(expectedRes, jobResult.InnerXml);
+ }
+
+ /// <summary>
+ /// Tests custom serialization binder.
+ /// </summary>
+ [Test]
+ public void TestSerializationBinder()
+ {
+ const int count = 50;
+
+ var cache = Ignition.GetIgnite(null).GetOrCreateCache<int, object>("cache");
+
+ // Put multiple objects from multiple same-named assemblies to cache
+ for (var i = 0; i < count; i++)
+ {
+ dynamic val = Activator.CreateInstance(GenerateDynamicType());
+
+ val.Id = i;
+ val.Name = "Name_" + i;
+
+ cache.Put(i, val);
+ }
+
+ // Verify correct deserialization
+ for (var i = 0; i < count; i++)
+ {
+ dynamic val = cache.Get(i);
+
+ Assert.AreEqual(val.Id, i);
+ Assert.AreEqual(val.Name, "Name_" + i);
+ }
+ }
+
+ /// <summary>
+ /// Generates a Type in runtime, puts it into a dynamic assembly.
+ /// </summary>
+ /// <returns></returns>
+ private static Type GenerateDynamicType()
+ {
+ var asmBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(
+ new AssemblyName("GridSerializationTestDynamicAssembly"), AssemblyBuilderAccess.Run);
+
+ var moduleBuilder = asmBuilder.DefineDynamicModule("GridSerializationTestDynamicModule");
+
+ var typeBuilder = moduleBuilder.DefineType("GridSerializationTestDynamicType",
+ TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.Serializable);
+
+ typeBuilder.DefineField("Id", typeof (int), FieldAttributes.Public);
+
+ typeBuilder.DefineField("Name", typeof (string), FieldAttributes.Public);
+
+ return typeBuilder.CreateType();
+ }
+ }
+
+ [Serializable]
+ [DataContract]
+ public sealed class SerializableXmlDoc : XmlDocument, ISerializable
+ {
+ /// <summary>
+ /// Default ctor.
+ /// </summary>
+ public SerializableXmlDoc()
+ {
+ // No-op
+ }
+
+ /// <summary>
+ /// Serialization ctor.
+ /// </summary>
+ private SerializableXmlDoc(SerializationInfo info, StreamingContext context)
+ {
+ LoadXml(info.GetString("xmlDocument"));
+ }
+
+ /** <inheritdoc /> */
+ public void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ info.AddValue("xmlDocument", OuterXml, typeof(string));
+ }
+ }
+
+ [Serializable]
+ public class CombineStringsTask : IComputeTask<object, string, SerializableXmlDoc>
+ {
+ public IDictionary<IComputeJob<string>, IClusterNode> Map(IList<IClusterNode> subgrid, object arg)
+ {
+ return subgrid.ToDictionary(x => (IComputeJob<string>) new ToStringJob {Arg = arg}, x => x);
+ }
+
+ public ComputeJobResultPolicy OnResult(IComputeJobResult<string> res, IList<IComputeJobResult<string>> rcvd)
+ {
+ return ComputeJobResultPolicy.Wait;
+ }
+
+ public SerializableXmlDoc Reduce(IList<IComputeJobResult<string>> results)
+ {
+ var result = new SerializableXmlDoc();
+
+ result.LoadXml(CombineStrings(results.Select(x => x.Data)));
+
+ return result;
+ }
+
+ public static string CombineStrings(IEnumerable<string> strings)
+ {
+ var text = string.Concat(strings.Select(x => string.Format("<val>{0}</val>", x)));
+
+ return string.Format("<document>{0}</document>", text);
+ }
+ }
+
+ [Serializable]
+ public class ToStringJob : IComputeJob<string>
+ {
+ /// <summary>
+ /// Job argument.
+ /// </summary>
+ public object Arg { get; set; }
+
+ /** <inheritdoc /> */
+ public string Execute()
+ {
+ return Arg.ToString();
+ }
+
+ /** <inheritdoc /> */
+ public void Cancel()
+ {
+ // No-op.
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/Serializable/BasicSerializableObjectsTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/Serializable/BasicSerializableObjectsTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/Serializable/BasicSerializableObjectsTest.cs
new file mode 100644
index 0000000..82deb3c
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/Serializable/BasicSerializableObjectsTest.cs
@@ -0,0 +1,124 @@
+\ufeff/*
+ * 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.Tests.Binary.Serializable
+{
+ using System;
+ using System.Runtime.Serialization;
+ using Apache.Ignite.Core.Binary;
+ using NUnit.Framework;
+
+ /// <summary>
+ /// Tests basic ISerializable scenarios.
+ /// </summary>
+ public class BasicSerializableObjectsTest
+ {
+ /// <summary>
+ /// Tests the object with no fields.
+ /// </summary>
+ [Test]
+ public void TestEmptyObject()
+ {
+ var res = TestUtils.SerializeDeserialize(new EmptyObject());
+
+ Assert.IsNotNull(res);
+ }
+
+ /// <summary>
+ /// Tests the object with no fields.
+ /// </summary>
+ [Test]
+ public void TestEmptyObjectOnline()
+ {
+ using (var ignite = Ignition.Start(TestUtils.GetTestConfiguration()))
+ {
+ var cache = ignite.CreateCache<int, EmptyObject>("c");
+
+ cache[1] = new EmptyObject();
+
+ var res = cache[1];
+
+ Assert.IsNotNull(res);
+ }
+ }
+
+ /// <summary>
+ /// Tests ISerializable without serialization ctor.
+ /// </summary>
+ [Test]
+ public void TestMissingCtor()
+ {
+ var ex = Assert.Throws<SerializationException>(() => TestUtils.SerializeDeserialize(new MissingCtor()));
+ Assert.AreEqual(string.Format("The constructor to deserialize an object of type '{0}' was not found.",
+ typeof(MissingCtor)), ex.Message);
+ }
+
+ /// <summary>
+ /// Tests <see cref="Type"/> serialization.
+ /// </summary>
+ [Test]
+ public void TestTypes()
+ {
+ var type = GetType();
+
+ var res = TestUtils.SerializeDeserialize(type);
+
+ Assert.AreEqual(type, res);
+ }
+
+ /// <summary>
+ /// Missing serialization ctor.
+ /// </summary>
+ private class MissingCtor : ISerializable
+ {
+ /** <inheritdoc /> */
+ public void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ // No-op.
+ }
+ }
+
+ /// <summary>
+ /// Object with no fields.
+ /// </summary>
+ [Serializable]
+ private class EmptyObject : ISerializable
+ {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="EmptyObject"/> class.
+ /// </summary>
+ public EmptyObject()
+ {
+ // No-op.
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="EmptyObject"/> class.
+ /// </summary>
+ private EmptyObject(SerializationInfo info, StreamingContext context)
+ {
+ Assert.IsInstanceOf<IBinaryReader>(context.Context);
+ }
+
+ /** <inheritdoc /> */
+ public void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ Assert.IsInstanceOf<IBinaryWriter>(context.Context);
+ }
+ }
+ }
+}
[2/5] ignite git commit: IGNITE-2703 .NET: Dynamic type registration
Posted by pt...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Io/BinaryStreamAdapter.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Io/BinaryStreamAdapter.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Io/BinaryStreamAdapter.cs
deleted file mode 100644
index b062689..0000000
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Io/BinaryStreamAdapter.cs
+++ /dev/null
@@ -1,119 +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.IO
-{
- using System;
- using System.Diagnostics.CodeAnalysis;
- using System.IO;
-
- /// <summary>
- /// Adapter providing .Net streaming functionality over the binary stream.
- /// </summary>
- internal class BinaryStreamAdapter : Stream
- {
- /// <summary>
- ///
- /// </summary>
- private readonly IBinaryStream _stream;
-
- /// <summary>
- /// Constructor.
- /// </summary>
- /// <param name="stream">Stream.</param>
- public BinaryStreamAdapter(IBinaryStream stream)
- {
- _stream = stream;
- }
-
- /** <inheritDoc /> */
- public override void Write(byte[] buffer, int offset, int count)
- {
- _stream.Write(buffer, offset, count);
- }
-
- /** <inheritDoc /> */
- public override int Read(byte[] buffer, int offset, int count)
- {
- _stream.Read(buffer, offset, count);
-
- return count;
- }
-
- /** <inheritDoc /> */
- public override void Flush()
- {
- // No-op.
- }
-
- /** <inheritDoc /> */
- public override bool CanRead
- {
- get { return true; }
- }
-
- /** <inheritDoc /> */
- public override bool CanWrite
- {
- get { return true; }
- }
-
- /** <inheritDoc /> */
- public override bool CanSeek
- {
- get { return false; }
- }
-
- /** <inheritDoc /> */
- [ExcludeFromCodeCoverage]
- public override long Seek(long offset, SeekOrigin origin)
- {
- throw new NotSupportedException("Stream is not seekable.");
- }
-
- /** <inheritDoc /> */
- [ExcludeFromCodeCoverage]
- public override long Position
- {
- get
- {
- throw new NotSupportedException("Stream is not seekable.");
- }
- set
- {
- throw new NotSupportedException("Stream is not seekable.");
- }
- }
-
- /** <inheritDoc /> */
- [ExcludeFromCodeCoverage]
- public override long Length
- {
- get
- {
- throw new NotSupportedException("Stream is not seekable.");
- }
- }
-
- /** <inheritDoc /> */
- [ExcludeFromCodeCoverage]
- public override void SetLength(long value)
- {
- throw new NotSupportedException("Stream is not seekable.");
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Marshaller.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Marshaller.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Marshaller.cs
index b929f3a..5effc5c 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Marshaller.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Marshaller.cs
@@ -21,6 +21,7 @@ namespace Apache.Ignite.Core.Impl.Binary
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
+ using System.Runtime.Serialization;
using Apache.Ignite.Core.Binary;
using Apache.Ignite.Core.Cache.Affinity;
using Apache.Ignite.Core.Common;
@@ -33,6 +34,7 @@ namespace Apache.Ignite.Core.Impl.Binary
using Apache.Ignite.Core.Impl.Compute.Closure;
using Apache.Ignite.Core.Impl.Datastream;
using Apache.Ignite.Core.Impl.Messaging;
+ using Apache.Ignite.Core.Log;
/// <summary>
/// Marshaller implementation.
@@ -43,37 +45,43 @@ namespace Apache.Ignite.Core.Impl.Binary
private readonly BinaryConfiguration _cfg;
/** Type to descriptor map. */
- private readonly IDictionary<Type, IBinaryTypeDescriptor> _typeToDesc =
- new Dictionary<Type, IBinaryTypeDescriptor>();
+ private readonly CopyOnWriteConcurrentDictionary<Type, BinaryFullTypeDescriptor> _typeToDesc =
+ new CopyOnWriteConcurrentDictionary<Type, BinaryFullTypeDescriptor>();
/** Type name to descriptor map. */
- private readonly IDictionary<string, IBinaryTypeDescriptor> _typeNameToDesc =
- new Dictionary<string, IBinaryTypeDescriptor>();
+ private readonly CopyOnWriteConcurrentDictionary<string, BinaryFullTypeDescriptor> _typeNameToDesc =
+ new CopyOnWriteConcurrentDictionary<string, BinaryFullTypeDescriptor>();
/** ID to descriptor map. */
- private readonly CopyOnWriteConcurrentDictionary<long, IBinaryTypeDescriptor> _idToDesc =
- new CopyOnWriteConcurrentDictionary<long, IBinaryTypeDescriptor>();
+ private readonly CopyOnWriteConcurrentDictionary<long, BinaryFullTypeDescriptor> _idToDesc =
+ new CopyOnWriteConcurrentDictionary<long, BinaryFullTypeDescriptor>();
- /** Cached metadatas. */
- private volatile IDictionary<int, BinaryTypeHolder> _metas =
- new Dictionary<int, BinaryTypeHolder>();
+ /** Cached binary types. */
+ private volatile IDictionary<int, BinaryTypeHolder> _metas = new Dictionary<int, BinaryTypeHolder>();
+
+ /** */
+ private volatile Ignite _ignite;
+
+ /** */
+ private readonly ILogger _log;
/// <summary>
/// Constructor.
/// </summary>
/// <param name="cfg">Configuration.</param>
- public Marshaller(BinaryConfiguration cfg)
+ /// <param name="log"></param>
+ public Marshaller(BinaryConfiguration cfg, ILogger log = null)
{
- // Validation.
- if (cfg == null)
- cfg = new BinaryConfiguration();
+ _cfg = cfg ?? new BinaryConfiguration();
+
+ _log = log;
- CompactFooter = cfg.CompactFooter;
+ CompactFooter = _cfg.CompactFooter;
- if (cfg.TypeConfigurations == null)
- cfg.TypeConfigurations = new List<BinaryTypeConfiguration>();
+ if (_cfg.TypeConfigurations == null)
+ _cfg.TypeConfigurations = new List<BinaryTypeConfiguration>();
- foreach (BinaryTypeConfiguration typeCfg in cfg.TypeConfigurations)
+ foreach (BinaryTypeConfiguration typeCfg in _cfg.TypeConfigurations)
{
if (string.IsNullOrEmpty(typeCfg.TypeName))
throw new BinaryObjectException("Type name cannot be null or empty: " + typeCfg);
@@ -85,25 +93,32 @@ namespace Apache.Ignite.Core.Impl.Binary
// 2. Define user types.
var typeResolver = new TypeResolver();
- ICollection<BinaryTypeConfiguration> typeCfgs = cfg.TypeConfigurations;
+ ICollection<BinaryTypeConfiguration> typeCfgs = _cfg.TypeConfigurations;
if (typeCfgs != null)
foreach (BinaryTypeConfiguration typeCfg in typeCfgs)
AddUserType(cfg, typeCfg, typeResolver);
- var typeNames = cfg.Types;
+ var typeNames = _cfg.Types;
if (typeNames != null)
foreach (string typeName in typeNames)
AddUserType(cfg, new BinaryTypeConfiguration(typeName), typeResolver);
-
- _cfg = cfg;
}
/// <summary>
/// Gets or sets the backing grid.
/// </summary>
- public Ignite Ignite { get; set; }
+ public Ignite Ignite
+ {
+ get { return _ignite; }
+ set
+ {
+ Debug.Assert(value != null);
+
+ _ignite = value;
+ }
+ }
/// <summary>
/// Gets the compact footer flag.
@@ -111,6 +126,12 @@ namespace Apache.Ignite.Core.Impl.Binary
public bool CompactFooter { get; set; }
/// <summary>
+ /// Gets or sets a value indicating whether type registration is disabled.
+ /// This may be desirable for static system marshallers where everything is written in unregistered mode.
+ /// </summary>
+ public bool RegistrationDisabled { get; set; }
+
+ /// <summary>
/// Marshal object.
/// </summary>
/// <param name="val">Value.</param>
@@ -126,11 +147,10 @@ namespace Apache.Ignite.Core.Impl.Binary
}
/// <summary>
- /// Marshal object.
+ /// Marshals an object.
/// </summary>
/// <param name="val">Value.</param>
/// <param name="stream">Output stream.</param>
- /// <returns>Collection of metadatas (if any).</returns>
private void Marshal<T>(T val, IBinaryStream stream)
{
BinaryWriter writer = StartMarshal(stream);
@@ -358,17 +378,20 @@ namespace Apache.Ignite.Core.Impl.Binary
_metas[meta.TypeId].Merge(mergeInfo);
}
}
-
+
/// <summary>
/// Gets descriptor for type.
/// </summary>
/// <param name="type">Type.</param>
- /// <returns>Descriptor.</returns>
+ /// <returns>
+ /// Descriptor.
+ /// </returns>
public IBinaryTypeDescriptor GetDescriptor(Type type)
{
- IBinaryTypeDescriptor desc;
+ BinaryFullTypeDescriptor desc;
- _typeToDesc.TryGetValue(type, out desc);
+ if (!_typeToDesc.TryGetValue(type, out desc) || !desc.IsRegistered)
+ desc = RegisterType(type, desc);
return desc;
}
@@ -380,10 +403,11 @@ namespace Apache.Ignite.Core.Impl.Binary
/// <returns>Descriptor.</returns>
public IBinaryTypeDescriptor GetDescriptor(string typeName)
{
- IBinaryTypeDescriptor desc;
+ BinaryFullTypeDescriptor desc;
- return _typeNameToDesc.TryGetValue(typeName, out desc) ? desc :
- new BinarySurrogateTypeDescriptor(_cfg, typeName);
+ return _typeNameToDesc.TryGetValue(typeName, out desc)
+ ? (IBinaryTypeDescriptor) desc
+ : new BinarySurrogateTypeDescriptor(_cfg, typeName);
}
/// <summary>
@@ -391,24 +415,43 @@ namespace Apache.Ignite.Core.Impl.Binary
/// </summary>
/// <param name="userType">User type flag.</param>
/// <param name="typeId">Type id.</param>
- /// <returns>Descriptor.</returns>
- public IBinaryTypeDescriptor GetDescriptor(bool userType, int typeId)
+ /// <param name="requiresType">
+ /// If set to true, resulting descriptor must have Type property populated.
+ /// <para />
+ /// When working in binary mode, we don't need Type. And there is no Type at all in some cases.
+ /// So we should not attempt to call BinaryProcessor right away.
+ /// Only when we really deserialize the value, requiresType is set to true
+ /// and we attempt to resolve the type by all means.
+ /// </param>
+ /// <returns>
+ /// Descriptor.
+ /// </returns>
+ public IBinaryTypeDescriptor GetDescriptor(bool userType, int typeId, bool requiresType = false)
{
- IBinaryTypeDescriptor desc;
+ BinaryFullTypeDescriptor desc;
var typeKey = BinaryUtils.TypeKey(userType, typeId);
- if (_idToDesc.TryGetValue(typeKey, out desc))
+ if (_idToDesc.TryGetValue(typeKey, out desc) && (!requiresType || desc.Type != null))
return desc;
if (!userType)
return null;
+ if (requiresType)
+ {
+ // Check marshaller context for dynamically registered type.
+ var type = _ignite == null ? null : _ignite.BinaryProcessor.GetType(typeId);
+
+ if (type != null)
+ return AddUserType(type, typeId, BinaryUtils.GetTypeName(type), true, desc);
+ }
+
var meta = GetBinaryType(typeId);
if (meta != BinaryType.Empty)
{
- desc = new BinaryFullTypeDescriptor(null, meta.TypeId, meta.TypeName, true, null, null, null, false,
+ desc = new BinaryFullTypeDescriptor(null, meta.TypeId, meta.TypeName, true, null, null, null, false,
meta.AffinityKeyFieldName, meta.IsEnum, null);
_idToDesc.GetOrAdd(typeKey, _ => desc);
@@ -416,13 +459,30 @@ namespace Apache.Ignite.Core.Impl.Binary
return desc;
}
- return new BinarySurrogateTypeDescriptor(_cfg, typeId);
+ return new BinarySurrogateTypeDescriptor(_cfg, typeId, null);
+ }
+
+ /// <summary>
+ /// Registers the type.
+ /// </summary>
+ /// <param name="type">The type.</param>
+ /// <param name="desc">Existing descriptor.</param>
+ private BinaryFullTypeDescriptor RegisterType(Type type, BinaryFullTypeDescriptor desc)
+ {
+ Debug.Assert(type != null);
+
+ var typeName = BinaryUtils.GetTypeName(type);
+ var typeId = BinaryUtils.TypeId(typeName, _cfg.DefaultNameMapper, _cfg.DefaultIdMapper);
+
+ var registered = _ignite != null && _ignite.BinaryProcessor.RegisterType(typeId, type);
+
+ return AddUserType(type, typeId, typeName, registered, desc);
}
/// <summary>
/// Gets the user type descriptors.
/// </summary>
- public ICollection<IBinaryTypeDescriptor> GetUserTypeDescriptors()
+ public ICollection<BinaryFullTypeDescriptor> GetUserTypeDescriptors()
{
return _typeNameToDesc.Values;
}
@@ -430,18 +490,67 @@ namespace Apache.Ignite.Core.Impl.Binary
/// <summary>
/// Add user type.
/// </summary>
- /// <param name="cfg">Configuration.</param>
+ /// <param name="type">The type.</param>
+ /// <param name="typeId">The type id.</param>
+ /// <param name="typeName">Name of the type.</param>
+ /// <param name="registered">Registered flag.</param>
+ /// <param name="desc">Existing descriptor.</param>
+ /// <returns>Descriptor.</returns>
+ private BinaryFullTypeDescriptor AddUserType(Type type, int typeId, string typeName, bool registered,
+ BinaryFullTypeDescriptor desc)
+ {
+ Debug.Assert(type != null);
+ Debug.Assert(typeName != null);
+
+ var ser = GetSerializer(_cfg, null, type, typeId, null, null, _log);
+
+ desc = desc == null
+ ? new BinaryFullTypeDescriptor(type, typeId, typeName, true, _cfg.DefaultNameMapper,
+ _cfg.DefaultIdMapper, ser, false, null, type.IsEnum, null, registered)
+ : new BinaryFullTypeDescriptor(desc, type, ser, registered);
+
+ if (RegistrationDisabled)
+ return desc;
+
+ var typeKey = BinaryUtils.TypeKey(true, typeId);
+
+ var desc0 = _idToDesc.GetOrAdd(typeKey, x => desc);
+ if (desc0.Type != null && desc0.Type.FullName != type.FullName)
+ ThrowConflictingTypeError(type, desc0.Type, typeId);
+
+ desc0 = _typeNameToDesc.GetOrAdd(typeName, x => desc);
+ if (desc0.Type != null && desc0.Type.FullName != type.FullName)
+ ThrowConflictingTypeError(type, desc0.Type, typeId);
+
+ _typeToDesc.Set(type, desc);
+
+ return desc;
+ }
+
+ /// <summary>
+ /// Throws the conflicting type error.
+ /// </summary>
+ private static void ThrowConflictingTypeError(object type1, object type2, int typeId)
+ {
+ throw new BinaryObjectException(string.Format("Conflicting type IDs [type1='{0}', " +
+ "type2='{1}', typeId={2}]", type1, type2, typeId));
+ }
+
+ /// <summary>
+ /// Add user type.
+ /// </summary>
+ /// <param name="cfg">The binary configuration.</param>
/// <param name="typeCfg">Type configuration.</param>
/// <param name="typeResolver">The type resolver.</param>
- private void AddUserType(BinaryConfiguration cfg, BinaryTypeConfiguration typeCfg,
- TypeResolver typeResolver)
+ /// <exception cref="BinaryObjectException"></exception>
+ private void AddUserType(BinaryConfiguration cfg, BinaryTypeConfiguration typeCfg, TypeResolver typeResolver)
{
// Get converter/mapper/serializer.
- IBinaryNameMapper nameMapper = typeCfg.NameMapper ?? cfg.DefaultNameMapper;
+ IBinaryNameMapper nameMapper = typeCfg.NameMapper ?? _cfg.DefaultNameMapper;
- IBinaryIdMapper idMapper = typeCfg.IdMapper ?? cfg.DefaultIdMapper;
+ IBinaryIdMapper idMapper = typeCfg.IdMapper ?? _cfg.DefaultIdMapper;
- bool keepDeserialized = typeCfg.KeepDeserialized ?? cfg.DefaultKeepDeserialized;
+ bool keepDeserialized = typeCfg.KeepDeserialized ?? _cfg.DefaultKeepDeserialized;
// Try resolving type.
Type type = typeResolver.ResolveType(typeCfg.TypeName);
@@ -459,7 +568,7 @@ namespace Apache.Ignite.Core.Impl.Binary
var typeName = BinaryUtils.GetTypeName(type);
int typeId = BinaryUtils.TypeId(typeName, nameMapper, idMapper);
var affKeyFld = typeCfg.AffinityKeyFieldName ?? GetAffinityKeyFieldNameFromAttribute(type);
- var serializer = GetSerializer(cfg, typeCfg, type, typeId, nameMapper, idMapper);
+ var serializer = GetSerializer(cfg, typeCfg, type, typeId, nameMapper, idMapper, _log);
AddType(type, typeId, typeName, true, keepDeserialized, nameMapper, idMapper, serializer,
affKeyFld, type.IsEnum, typeCfg.EqualityComparer);
@@ -479,16 +588,25 @@ namespace Apache.Ignite.Core.Impl.Binary
/// <summary>
/// Gets the serializer.
/// </summary>
- private static IBinarySerializerInternal GetSerializer(BinaryConfiguration cfg, BinaryTypeConfiguration typeCfg,
- Type type, int typeId, IBinaryNameMapper nameMapper, IBinaryIdMapper idMapper)
+ private static IBinarySerializerInternal GetSerializer(BinaryConfiguration cfg,
+ BinaryTypeConfiguration typeCfg, Type type, int typeId, IBinaryNameMapper nameMapper,
+ IBinaryIdMapper idMapper, ILogger log)
{
- var serializer = typeCfg.Serializer ?? cfg.DefaultSerializer;
+ var serializer = (typeCfg != null ? typeCfg.Serializer : null) ??
+ (cfg != null ? cfg.DefaultSerializer : null);
if (serializer == null)
{
if (type.GetInterfaces().Contains(typeof(IBinarizable)))
return BinarizableSerializer.Instance;
+ if (type.GetInterfaces().Contains(typeof(ISerializable)))
+ {
+ LogSerializableWarning(type, log);
+
+ return new SerializableSerializer(type);
+ }
+
serializer = new BinaryReflectiveSerializer();
}
@@ -531,14 +649,14 @@ namespace Apache.Ignite.Core.Impl.Binary
/// <param name="affKeyFieldName">Affinity key field name.</param>
/// <param name="isEnum">Enum flag.</param>
/// <param name="comparer">Comparer.</param>
- private void AddType(Type type, int typeId, string typeName, bool userType,
+ private void AddType(Type type, int typeId, string typeName, bool userType,
bool keepDeserialized, IBinaryNameMapper nameMapper, IBinaryIdMapper idMapper,
- IBinarySerializerInternal serializer, string affKeyFieldName, bool isEnum,
+ IBinarySerializerInternal serializer, string affKeyFieldName, bool isEnum,
IEqualityComparer<IBinaryObject> comparer)
{
long typeKey = BinaryUtils.TypeKey(userType, typeId);
- IBinaryTypeDescriptor conflictingType;
+ BinaryFullTypeDescriptor conflictingType;
if (_idToDesc.TryGetValue(typeKey, out conflictingType))
{
@@ -548,8 +666,7 @@ namespace Apache.Ignite.Core.Impl.Binary
var type2 = type != null ? type.AssemblyQualifiedName : typeName;
- throw new BinaryObjectException(string.Format("Conflicting type IDs [type1='{0}', " +
- "type2='{1}', typeId={2}]", type1, type2, typeId));
+ ThrowConflictingTypeError(type1, type2, typeId);
}
if (userType && _typeNameToDesc.ContainsKey(typeName))
@@ -559,10 +676,10 @@ namespace Apache.Ignite.Core.Impl.Binary
serializer, keepDeserialized, affKeyFieldName, isEnum, comparer);
if (type != null)
- _typeToDesc[type] = descriptor;
+ _typeToDesc.GetOrAdd(type, x => descriptor);
if (userType)
- _typeNameToDesc[typeName] = descriptor;
+ _typeNameToDesc.GetOrAdd(typeName, x => descriptor);
_idToDesc.GetOrAdd(typeKey, _ => descriptor);
}
@@ -570,7 +687,7 @@ namespace Apache.Ignite.Core.Impl.Binary
/// <summary>
/// Adds a predefined system type.
/// </summary>
- private void AddSystemType<T>(int typeId, Func<BinaryReader, T> ctor, string affKeyFldName = null,
+ private void AddSystemType<T>(int typeId, Func<BinaryReader, T> ctor, string affKeyFldName = null,
IBinarySerializerInternal serializer = null)
where T : IBinaryWriteAware
{
@@ -599,10 +716,6 @@ namespace Apache.Ignite.Core.Impl.Binary
AddSystemType(BinaryUtils.TypeComputeFuncJob, r => new ComputeFuncJob(r));
AddSystemType(BinaryUtils.TypeComputeActionJob, r => new ComputeActionJob(r));
AddSystemType(BinaryUtils.TypeContinuousQueryRemoteFilterHolder, r => new ContinuousQueryFilterHolder(r));
- AddSystemType(BinaryUtils.TypeSerializableHolder, r => new SerializableObjectHolder(r),
- serializer: new SerializableSerializer());
- AddSystemType(BinaryUtils.TypeDateTimeHolder, r => new DateTimeHolder(r),
- serializer: new DateTimeSerializer());
AddSystemType(BinaryUtils.TypeCacheEntryProcessorHolder, r => new CacheEntryProcessorHolder(r));
AddSystemType(BinaryUtils.TypeCacheEntryPredicateHolder, r => new CacheEntryFilterHolder(r));
AddSystemType(BinaryUtils.TypeMessageListenerHolder, r => new MessageListenerHolder(r));
@@ -612,5 +725,20 @@ namespace Apache.Ignite.Core.Impl.Binary
AddSystemType(0, r => new ObjectInfoHolder(r));
AddSystemType(BinaryUtils.TypeIgniteUuid, r => new IgniteGuid(r));
}
+
+ /// <summary>
+ /// Logs the warning about ISerializable pitfalls.
+ /// </summary>
+ private static void LogSerializableWarning(Type type, ILogger log)
+ {
+ if (log == null)
+ return;
+
+ log.GetLogger(typeof(Marshaller).Name)
+ .Warn("Type '{0}' implements '{1}'. It will be written in Ignite binary format, however, " +
+ "the following limitations apply: " +
+ "DateTime fields would not work in SQL; " +
+ "sbyte, ushort, uint, ulong fields would not work in DML.", type, typeof(ISerializable));
+ }
}
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/ReflectionUtils.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/ReflectionUtils.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/ReflectionUtils.cs
new file mode 100644
index 0000000..50c51a7
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/ReflectionUtils.cs
@@ -0,0 +1,50 @@
+\ufeff/*
+ * 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;
+
+ /// <summary>
+ /// Reflection utils.
+ /// </summary>
+ internal static class ReflectionUtils
+ {
+ /// <summary>
+ /// Gets all fields, including base classes.
+ /// </summary>
+ public static IEnumerable<FieldInfo> GetAllFields(Type type)
+ {
+ const BindingFlags flags = BindingFlags.Instance | BindingFlags.Public |
+ BindingFlags.NonPublic | BindingFlags.DeclaredOnly;
+
+ var curType = type;
+
+ while (curType != null)
+ {
+ foreach (var field in curType.GetFields(flags))
+ {
+ yield return field;
+ }
+
+ curType = curType.BaseType;
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/SerializableObjectHolder.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/SerializableObjectHolder.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/SerializableObjectHolder.cs
deleted file mode 100644
index 26b1d5f..0000000
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/SerializableObjectHolder.cs
+++ /dev/null
@@ -1,96 +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.Diagnostics;
- using System.Runtime.Serialization.Formatters.Binary;
- using Apache.Ignite.Core.Binary;
- using Apache.Ignite.Core.Impl.Binary.IO;
-
- /// <summary>
- /// Wraps Serializable item in a binarizable.
- /// </summary>
- internal class SerializableObjectHolder : IBinaryWriteAware
- {
- /** */
- private readonly object _item;
-
- /// <summary>
- /// Initializes a new instance of the <see cref="SerializableObjectHolder"/> class.
- /// </summary>
- /// <param name="item">The item to wrap.</param>
- public SerializableObjectHolder(object item)
- {
- _item = item;
- }
-
- /// <summary>
- /// Gets the item to wrap.
- /// </summary>
- public object Item
- {
- get { return _item; }
- }
-
- /** <inheritDoc /> */
- public void WriteBinary(IBinaryWriter writer)
- {
- Debug.Assert(writer != null);
-
- var writer0 = (BinaryWriter)writer.GetRawWriter();
-
- writer0.WithDetach(w =>
- {
- using (var streamAdapter = new BinaryStreamAdapter(w.Stream))
- {
- new BinaryFormatter().Serialize(streamAdapter, Item);
- }
- });
- }
-
- /// <summary>
- /// Initializes a new instance of the <see cref="SerializableObjectHolder"/> class.
- /// </summary>
- /// <param name="reader">The reader.</param>
- public SerializableObjectHolder(BinaryReader reader)
- {
- Debug.Assert(reader != null);
-
- using (var streamAdapter = new BinaryStreamAdapter(reader.Stream))
- {
- _item = new BinaryFormatter().Deserialize(streamAdapter, null);
- }
- }
-
- /** <inheritdoc /> */
- public override bool Equals(object obj)
- {
- if (ReferenceEquals(null, obj)) return false;
- if (ReferenceEquals(this, obj)) return true;
- if (obj.GetType() != GetType()) return false;
-
- return Equals(_item, ((SerializableObjectHolder) obj)._item);
- }
-
- /** <inheritdoc /> */
- public override int GetHashCode()
- {
- return _item != null ? _item.GetHashCode() : 0;
- }
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/SerializableSerializer.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/SerializableSerializer.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/SerializableSerializer.cs
index 55ac3c0..6c7076a 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/SerializableSerializer.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/SerializableSerializer.cs
@@ -1,4 +1,4 @@
-/*
+\ufeff/*
* 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.
@@ -18,31 +18,667 @@
namespace Apache.Ignite.Core.Impl.Binary
{
using System;
+ using System.Collections.Generic;
+ using System.IO;
+ using System.Linq;
+ using System.Runtime.Serialization;
+ using Apache.Ignite.Core.Binary;
+ using Apache.Ignite.Core.Impl.Binary.Metadata;
using Apache.Ignite.Core.Impl.Common;
/// <summary>
- /// Serializable serializer.
+ /// Serializes classes that implement <see cref="ISerializable"/>.
/// </summary>
internal class SerializableSerializer : IBinarySerializerInternal
{
+ /** */
+ private readonly SerializableTypeDescriptor _serializableTypeDesc;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="SerializableSerializer"/> class.
+ /// </summary>
+ public SerializableSerializer(Type type)
+ {
+ IgniteArgumentCheck.NotNull(type, "type");
+
+ _serializableTypeDesc = SerializableTypeDescriptor.Get(type);
+ }
+
/** <inheritdoc /> */
- public void WriteBinary<T>(T obj, BinaryWriter writer)
+ public bool SupportsHandles
{
- TypeCaster<SerializableObjectHolder>.Cast(obj).WriteBinary(writer);
+ get { return true; }
}
/** <inheritdoc /> */
- public T ReadBinary<T>(BinaryReader reader, Type type, int pos)
+ public void WriteBinary<T>(T obj, BinaryWriter writer)
{
- var holder = new SerializableObjectHolder(reader);
+ var ctx = GetStreamingContext(writer);
+ _serializableTypeDesc.OnSerializing(obj, ctx);
+
+ var serializable = (ISerializable) obj;
+ var objType = obj.GetType();
+
+ // Get field values and write them.
+ var serInfo = new SerializationInfo(objType, new FormatterConverter());
+ serializable.GetObjectData(serInfo, ctx);
- return TypeCaster<T>.Cast(holder.Item);
+ var dotNetFields = WriteSerializationInfo(writer, serInfo);
+
+ // Check if there is any additional information to be written.
+ var customType = GetCustomType(serInfo, serializable);
+
+ if (dotNetFields != null || writer.Marshaller.Ignite == null || customType != null)
+ {
+ // Set custom type flag in object header.
+ writer.SetCustomTypeDataFlag(true);
+
+ // Write additional information in raw mode.
+ writer.GetRawWriter();
+
+ WriteFieldNames(writer, serInfo);
+
+ WriteCustomTypeInfo(writer, customType);
+
+ WriteDotNetFields(writer, dotNetFields);
+ }
+
+ _serializableTypeDesc.OnSerialized(obj, ctx);
}
/** <inheritdoc /> */
- public bool SupportsHandles
+ public T ReadBinary<T>(BinaryReader reader, IBinaryTypeDescriptor desc, int pos)
+ {
+ object res;
+ var ctx = GetStreamingContext(reader);
+ var callbackPushed = false;
+
+ // Read additional information from raw part, if flag is set.
+ IEnumerable<string> fieldNames;
+ Type customType = null;
+ ICollection<int> dotNetFields = null;
+
+ if (reader.GetCustomTypeDataFlag())
+ {
+ var oldPos = reader.Stream.Position;
+ reader.SeekToRaw();
+
+ fieldNames = ReadFieldNames(reader, desc);
+ customType = ReadCustomTypeInfo(reader);
+ dotNetFields = ReadDotNetFields(reader);
+
+ // Restore stream position.
+ reader.Stream.Seek(oldPos, SeekOrigin.Begin);
+ }
+ else
+ {
+ fieldNames = GetBinaryTypeFields(reader, desc);
+ }
+
+ try
+ {
+ if (customType != null)
+ {
+ // Custom type is present, which returns original type via IObjectReference.
+ var serInfo = ReadSerializationInfo(reader, fieldNames, desc, dotNetFields);
+
+ res = ReadAsCustomType(customType, serInfo, ctx);
+
+ // Handle is added after entire object is deserialized,
+ // because handles should not point to a custom type wrapper.
+ reader.AddHandle(pos, res);
+
+ DeserializationCallbackProcessor.Push(res);
+ callbackPushed = true;
+ }
+ else
+ {
+ res = FormatterServices.GetUninitializedObject(desc.Type);
+
+ _serializableTypeDesc.OnDeserializing(res, ctx);
+
+ DeserializationCallbackProcessor.Push(res);
+ callbackPushed = true;
+
+ reader.AddHandle(pos, res);
+
+ // Read actual data and call constructor.
+ var serInfo = ReadSerializationInfo(reader, fieldNames, desc, dotNetFields);
+ _serializableTypeDesc.SerializationCtorUninitialized(res, serInfo, ctx);
+ }
+
+ _serializableTypeDesc.OnDeserialized(res, ctx);
+ }
+ finally
+ {
+ if (callbackPushed)
+ DeserializationCallbackProcessor.Pop();
+ }
+
+ return (T) res;
+ }
+
+ /// <summary>
+ /// Writes .NET-specific fields.
+ /// </summary>
+ private static void WriteDotNetFields(IBinaryRawWriter writer, ICollection<string> dotNetFields)
{
- get { return false; }
+ if (dotNetFields == null)
+ {
+ writer.WriteInt(0);
+
+ return;
+ }
+
+ writer.WriteInt(dotNetFields.Count);
+
+ foreach (var dotNetField in dotNetFields)
+ {
+ writer.WriteInt(BinaryUtils.GetStringHashCode(dotNetField));
+ }
+ }
+
+ /// <summary>
+ /// Writes .NET-specific fields.
+ /// </summary>
+ private static ICollection<int> ReadDotNetFields(IBinaryRawReader reader)
+ {
+ int count = reader.ReadInt();
+
+ if (count <= 0)
+ return null;
+
+ var res = new HashSet<int>();
+
+ for (int i = 0; i < count; i++)
+ {
+ res.Add(reader.ReadInt());
+ }
+
+ return res;
+ }
+
+ /// <summary>
+ /// Writes the field names.
+ /// </summary>
+ private static void WriteFieldNames(BinaryWriter writer, SerializationInfo serInfo)
+ {
+ if (writer.Marshaller.Ignite != null)
+ {
+ // Online mode: field names are in binary metadata.
+ writer.WriteInt(-1);
+ return;
+ }
+
+ // Offline mode: write all field names.
+ // Even if MemberCount is 0, write empty array to denote offline mode.
+ writer.WriteInt(serInfo.MemberCount);
+
+ foreach (var entry in serInfo)
+ {
+ writer.WriteString(entry.Name);
+ }
+ }
+
+ /// <summary>
+ /// Gets the field names.
+ /// </summary>
+ private static IEnumerable<string> ReadFieldNames(BinaryReader reader, IBinaryTypeDescriptor desc)
+ {
+ var fieldCount = reader.ReadInt();
+
+ if (fieldCount == 0)
+ return Enumerable.Empty<string>();
+
+ if (fieldCount > 0)
+ {
+ var fieldNames = new string[fieldCount];
+
+ for (var i = 0; i < fieldCount; i++)
+ {
+ fieldNames[i] = reader.ReadString();
+ }
+
+ return fieldNames;
+ }
+
+ // Negative field count: online mode.
+ return GetBinaryTypeFields(reader, desc);
+ }
+
+ /// <summary>
+ /// Gets the binary type fields.
+ /// </summary>
+ private static IEnumerable<string> GetBinaryTypeFields(BinaryReader reader, IBinaryTypeDescriptor desc)
+ {
+ var binaryType = reader.Marshaller.GetBinaryType(desc.TypeId);
+
+ if (binaryType == BinaryType.Empty)
+ {
+ // Object without fields.
+ return Enumerable.Empty<string>();
+ }
+
+ return binaryType.Fields;
+ }
+
+ /// <summary>
+ /// Writes the custom type information.
+ /// </summary>
+ private static void WriteCustomTypeInfo(BinaryWriter writer, Type customType)
+ {
+ var raw = writer.GetRawWriter();
+
+ if (customType != null)
+ {
+ raw.WriteBoolean(true);
+
+ var desc = writer.Marshaller.GetDescriptor(customType);
+
+ if (desc.IsRegistered)
+ {
+ raw.WriteBoolean(true);
+ raw.WriteInt(desc.TypeId);
+ }
+ else
+ {
+ raw.WriteBoolean(false);
+ raw.WriteString(customType.FullName);
+ }
+ }
+ else
+ {
+ raw.WriteBoolean(false);
+ }
+ }
+
+ /// <summary>
+ /// Gets the custom serialization type.
+ /// </summary>
+ private static Type GetCustomType(SerializationInfo serInfo, ISerializable serializable)
+ {
+ // ISerializable implementor may call SerializationInfo.SetType() or FullTypeName setter.
+ // In that case there is no serialization ctor on objType.
+ // Instead, we should instantiate specified custom type and then call IObjectReference.GetRealObject().
+ if (serInfo.IsFullTypeNameSetExplicit)
+ {
+ return new TypeResolver().ResolveType(serInfo.FullTypeName, serInfo.AssemblyName);
+ }
+
+ if (serInfo.ObjectType != serializable.GetType())
+ {
+ return serInfo.ObjectType;
+ }
+
+ return null;
+ }
+
+ /// <summary>
+ /// Reads the custom type information.
+ /// </summary>
+ private static Type ReadCustomTypeInfo(BinaryReader reader)
+ {
+ if (!reader.ReadBoolean())
+ return null;
+
+ Type customType;
+
+ if (reader.ReadBoolean())
+ {
+ // Registered type written as type id.
+ var typeId = reader.ReadInt();
+ customType = reader.Marshaller.GetDescriptor(true, typeId, true).Type;
+
+ if (customType == null)
+ {
+ throw new BinaryObjectException(string.Format(
+ "Failed to resolve custom type provided by SerializationInfo: [typeId={0}]", typeId));
+ }
+ }
+ else
+ {
+ // Unregistered type written as type name.
+ var typeName = reader.ReadString();
+ customType = new TypeResolver().ResolveType(typeName);
+
+ if (customType == null)
+ {
+ throw new BinaryObjectException(string.Format(
+ "Failed to resolve custom type provided by SerializationInfo: [typeName={0}]", typeName));
+ }
+ }
+
+ return customType;
+ }
+
+ /// <summary>
+ /// Writes the serialization information.
+ /// </summary>
+ private static List<string> WriteSerializationInfo(IBinaryWriter writer, SerializationInfo serInfo)
+ {
+ List<string> dotNetFields = null;
+
+ // Write fields.
+ foreach (var entry in GetEntries(serInfo).OrderBy(x => x.Name))
+ {
+ WriteEntry(writer, entry);
+
+ var type = entry.Value == null ? null : entry.Value.GetType();
+
+ if (type == typeof(sbyte) || type == typeof(ushort) || type == typeof(uint) || type == typeof(ulong)
+ || type == typeof(sbyte[]) || type == typeof(ushort[])
+ || type == typeof(uint[]) || type == typeof(ulong[]))
+ {
+ // Denote .NET-specific type.
+ dotNetFields = dotNetFields ?? new List<string>();
+
+ dotNetFields.Add(entry.Name);
+ }
+ }
+
+ return dotNetFields;
+ }
+
+ /// <summary>
+ /// Writes the serialization entry.
+ /// </summary>
+ private static void WriteEntry(IBinaryWriter writer, SerializationEntry entry)
+ {
+ unchecked
+ {
+ var type = entry.ObjectType;
+
+ if (type == typeof(byte))
+ {
+ writer.WriteByte(entry.Name, (byte) entry.Value);
+ }
+ else if (type == typeof(byte[]))
+ {
+ writer.WriteByteArray(entry.Name, (byte[]) entry.Value);
+ }
+ if (type == typeof(sbyte))
+ {
+ writer.WriteByte(entry.Name, (byte) (sbyte) entry.Value);
+ }
+ else if (type == typeof(sbyte[]))
+ {
+ writer.WriteByteArray(entry.Name, (byte[]) (Array) entry.Value);
+ }
+ else if (type == typeof(bool))
+ {
+ writer.WriteBoolean(entry.Name, (bool) entry.Value);
+ }
+ else if (type == typeof(bool[]))
+ {
+ writer.WriteBooleanArray(entry.Name, (bool[]) entry.Value);
+ }
+ else if (type == typeof(char))
+ {
+ writer.WriteChar(entry.Name, (char) entry.Value);
+ }
+ else if (type == typeof(char[]))
+ {
+ writer.WriteCharArray(entry.Name, (char[]) entry.Value);
+ }
+ else if (type == typeof(short))
+ {
+ writer.WriteShort(entry.Name, (short) entry.Value);
+ }
+ else if (type == typeof(short[]))
+ {
+ writer.WriteShortArray(entry.Name, (short[]) entry.Value);
+ }
+ else if (type == typeof(ushort))
+ {
+ writer.WriteShort(entry.Name, (short) (ushort) entry.Value);
+ }
+ else if (type == typeof(ushort[]))
+ {
+ writer.WriteShortArray(entry.Name, (short[]) (Array) entry.Value);
+ }
+ else if (type == typeof(int))
+ {
+ writer.WriteInt(entry.Name, (int) entry.Value);
+ }
+ else if (type == typeof(int[]))
+ {
+ writer.WriteIntArray(entry.Name, (int[]) entry.Value);
+ }
+ else if (type == typeof(uint))
+ {
+ writer.WriteInt(entry.Name, (int) (uint) entry.Value);
+ }
+ else if (type == typeof(uint[]))
+ {
+ writer.WriteIntArray(entry.Name, (int[]) (Array) entry.Value);
+ }
+ else if (type == typeof(long))
+ {
+ writer.WriteLong(entry.Name, (long) entry.Value);
+ }
+ else if (type == typeof(long[]))
+ {
+ writer.WriteLongArray(entry.Name, (long[]) entry.Value);
+ }
+ else if (type == typeof(ulong))
+ {
+ writer.WriteLong(entry.Name, (long) (ulong) entry.Value);
+ }
+ else if (type == typeof(ulong[]))
+ {
+ writer.WriteLongArray(entry.Name, (long[]) (Array) entry.Value);
+ }
+ else if (type == typeof(float))
+ {
+ writer.WriteFloat(entry.Name, (float) entry.Value);
+ }
+ else if (type == typeof(float[]))
+ {
+ writer.WriteFloatArray(entry.Name, (float[]) entry.Value);
+ }
+ else if (type == typeof(double))
+ {
+ writer.WriteDouble(entry.Name, (double) entry.Value);
+ }
+ else if (type == typeof(double[]))
+ {
+ writer.WriteDoubleArray(entry.Name, (double[]) entry.Value);
+ }
+ else if (type == typeof(decimal))
+ {
+ writer.WriteDecimal(entry.Name, (decimal) entry.Value);
+ }
+ else if (type == typeof(decimal?))
+ {
+ writer.WriteDecimal(entry.Name, (decimal?) entry.Value);
+ }
+ else if (type == typeof(decimal?[]))
+ {
+ writer.WriteDecimalArray(entry.Name, (decimal?[]) entry.Value);
+ }
+ else if (type == typeof(string))
+ {
+ writer.WriteString(entry.Name, (string) entry.Value);
+ }
+ else if (type == typeof(string[]))
+ {
+ writer.WriteStringArray(entry.Name, (string[]) entry.Value);
+ }
+ else if (type == typeof(Guid))
+ {
+ writer.WriteGuid(entry.Name, (Guid) entry.Value);
+ }
+ else if (type == typeof(Guid?))
+ {
+ writer.WriteGuid(entry.Name, (Guid?) entry.Value);
+ }
+ else if (type == typeof(Guid?[]))
+ {
+ writer.WriteGuidArray(entry.Name, (Guid?[]) entry.Value);
+ }
+ else
+ {
+ writer.WriteObject(entry.Name, entry.Value);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets the entries.
+ /// </summary>
+ private static IEnumerable<SerializationEntry> GetEntries(SerializationInfo serInfo)
+ {
+ foreach (var entry in serInfo)
+ {
+ yield return entry;
+ }
+ }
+
+ /// <summary>
+ /// Reads the serialization information.
+ /// </summary>
+ private static SerializationInfo ReadSerializationInfo(BinaryReader reader,
+ IEnumerable<string> fieldNames, IBinaryTypeDescriptor desc, ICollection<int> dotNetFields)
+ {
+ var serInfo = new SerializationInfo(desc.Type, new FormatterConverter());
+
+ if (dotNetFields == null)
+ {
+ foreach (var fieldName in fieldNames)
+ {
+ var fieldVal = reader.ReadObject<object>(fieldName);
+
+ serInfo.AddValue(fieldName, fieldVal);
+ }
+ }
+ else
+ {
+ foreach (var fieldName in fieldNames)
+ {
+ var fieldVal = ReadField(reader, fieldName, dotNetFields);
+
+ serInfo.AddValue(fieldName, fieldVal);
+ }
+ }
+
+ return serInfo;
+ }
+
+ /// <summary>
+ /// Reads the object as a custom type.
+ /// </summary>
+ private static object ReadAsCustomType(Type customType, SerializationInfo serInfo, StreamingContext ctx)
+ {
+ var ctorFunc = SerializableTypeDescriptor.Get(customType).SerializationCtor;
+
+ var customObj = ctorFunc(serInfo, ctx);
+
+ var wrapper = customObj as IObjectReference;
+
+ return wrapper == null
+ ? customObj
+ : wrapper.GetRealObject(ctx);
+ }
+
+ /// <summary>
+ /// Gets the streaming context.
+ /// </summary>
+ private static StreamingContext GetStreamingContext(IBinaryReader reader)
+ {
+ return new StreamingContext(StreamingContextStates.All, reader);
+ }
+
+ /// <summary>
+ /// Gets the streaming context.
+ /// </summary>
+ private static StreamingContext GetStreamingContext(IBinaryWriter writer)
+ {
+ return new StreamingContext(StreamingContextStates.All, writer);
+ }
+
+ /// <summary>
+ /// Reads the field.
+ /// <para />
+ /// Java side does not have counterparts for byte, ushort, uint, ulong.
+ /// For such fields we write a special boolean field indicating the type.
+ /// If special field is present, then the value has to be converted to .NET-specific type.
+ /// </summary>
+ private static object ReadField(IBinaryReader reader, string fieldName, ICollection<int> dotNetFields)
+ {
+ var fieldVal = reader.ReadObject<object>(fieldName);
+
+ if (fieldVal == null)
+ return null;
+
+ var fieldType = fieldVal.GetType();
+
+ unchecked
+ {
+ if (fieldType == typeof(byte))
+ {
+ return dotNetFields.Contains(BinaryUtils.GetStringHashCode(fieldName))
+ ? (sbyte) (byte) fieldVal : fieldVal;
+ }
+
+ if (fieldType == typeof(short))
+ {
+ return dotNetFields.Contains(BinaryUtils.GetStringHashCode(fieldName))
+ ? (ushort) (short) fieldVal : fieldVal;
+ }
+
+ if (fieldType == typeof(int))
+ {
+ return dotNetFields.Contains(BinaryUtils.GetStringHashCode(fieldName))
+ ? (uint) (int) fieldVal : fieldVal;
+ }
+
+ if (fieldType == typeof(long))
+ {
+ return dotNetFields.Contains(BinaryUtils.GetStringHashCode(fieldName))
+ ? (ulong) (long) fieldVal : fieldVal;
+ }
+
+ if (fieldType == typeof(byte[]))
+ {
+ return dotNetFields.Contains(BinaryUtils.GetStringHashCode(fieldName))
+ ? ConvertArray<byte, sbyte>((byte[]) fieldVal) : fieldVal;
+ }
+
+ if (fieldType == typeof(short[]))
+ {
+ return dotNetFields.Contains(BinaryUtils.GetStringHashCode(fieldName))
+ ? ConvertArray<short, ushort>((short[]) fieldVal) : fieldVal;
+ }
+
+ if (fieldType == typeof(int[]))
+ {
+ return dotNetFields.Contains(BinaryUtils.GetStringHashCode(fieldName))
+ ? ConvertArray<int, uint>((int[]) fieldVal) : fieldVal;
+ }
+
+ if (fieldType == typeof(long[]))
+ {
+ return dotNetFields.Contains(BinaryUtils.GetStringHashCode(fieldName))
+ ? ConvertArray<long, ulong>((long[]) fieldVal) : fieldVal;
+ }
+ }
+
+ return fieldVal;
+ }
+
+ /// <summary>
+ /// Converts the array.
+ /// </summary>
+ private static TU[] ConvertArray<T, TU>(T[] arr)
+ {
+ var res = new TU[arr.Length];
+
+ for (var i = 0; i < arr.Length; i++)
+ {
+ res[i] = TypeCaster<TU>.Cast(arr[i]);
+ }
+
+ return res;
}
}
-}
\ No newline at end of file
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/TypeResolver.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/TypeResolver.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/TypeResolver.cs
index 340dac4..36dde4b 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/TypeResolver.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/TypeResolver.cs
@@ -50,6 +50,13 @@ namespace Apache.Ignite.Core.Impl.Binary
{
Debug.Assert(!string.IsNullOrEmpty(typeName));
+ // Fully-qualified name can be resolved with system mechanism.
+ var type = Type.GetType(typeName, false);
+
+ if (type != null)
+ return type;
+
+ // Partial names should be resolved by scanning assemblies.
return ResolveType(assemblyName, typeName, AppDomain.CurrentDomain.GetAssemblies())
?? ResolveTypeInReferencedAssemblies(assemblyName, typeName);
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/UserSerializerProxy.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/UserSerializerProxy.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/UserSerializerProxy.cs
index de25e32..b0d393d 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/UserSerializerProxy.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/UserSerializerProxy.cs
@@ -17,7 +17,6 @@
namespace Apache.Ignite.Core.Impl.Binary
{
- using System;
using System.Diagnostics;
using System.Runtime.Serialization;
using Apache.Ignite.Core.Binary;
@@ -48,9 +47,9 @@ namespace Apache.Ignite.Core.Impl.Binary
}
/** <inheritdoc /> */
- public T ReadBinary<T>(BinaryReader reader, Type type, int pos)
+ public T ReadBinary<T>(BinaryReader reader, IBinaryTypeDescriptor desc, int pos)
{
- var obj = FormatterServices.GetUninitializedObject(type);
+ var obj = FormatterServices.GetUninitializedObject(desc.Type);
reader.AddHandle(pos, obj);
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/Affinity/AffinityFunctionSerializer.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/Affinity/AffinityFunctionSerializer.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/Affinity/AffinityFunctionSerializer.cs
index 5d940c5..73afe38 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/Affinity/AffinityFunctionSerializer.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/Affinity/AffinityFunctionSerializer.cs
@@ -255,9 +255,6 @@ namespace Apache.Ignite.Core.Impl.Cache.Affinity
return;
}
- if (func != null && !func.GetType().IsSerializable)
- throw new IgniteException("AffinityFunction should be serializable.");
-
writer.WriteObject(func);
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/CacheImpl.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/CacheImpl.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/CacheImpl.cs
index a387e1b..2523cf7 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/CacheImpl.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/CacheImpl.cs
@@ -150,7 +150,8 @@ namespace Apache.Ignite.Core.Impl.Cache
/** <inheritDoc /> */
public CacheConfiguration GetConfiguration()
{
- return DoInOp((int) CacheOp.GetConfig, stream => new CacheConfiguration(Marshaller.StartUnmarshal(stream)));
+ return DoInOp((int) CacheOp.GetConfig, stream => new CacheConfiguration(
+ BinaryUtils.Marshaller.StartUnmarshal(stream)));
}
/** <inheritDoc /> */
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/CopyOnWriteConcurrentDictionary.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/CopyOnWriteConcurrentDictionary.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/CopyOnWriteConcurrentDictionary.cs
index 01fc8a9..78cb8b6 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/CopyOnWriteConcurrentDictionary.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/CopyOnWriteConcurrentDictionary.cs
@@ -15,6 +15,7 @@
* limitations under the License.
*/
+// ReSharper disable InconsistentlySynchronizedField
namespace Apache.Ignite.Core.Impl.Common
{
using System;
@@ -69,5 +70,39 @@ namespace Apache.Ignite.Core.Impl.Common
return res;
}
}
+
+ /// <summary>
+ /// Sets a value for the key unconditionally.
+ /// </summary>
+ /// <param name="key">The key.</param>
+ /// <param name="value">The value.</param>
+ [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods")]
+ public void Set(TKey key, TValue value)
+ {
+ lock (this)
+ {
+ var dict0 = new Dictionary<TKey, TValue>(_dict);
+
+ dict0[key] = value;
+
+ _dict = dict0;
+ }
+ }
+
+ /// <summary>
+ /// Determines whether the specified key exists in the dictionary.
+ /// </summary>
+ public bool ContainsKey(TKey key)
+ {
+ return _dict.ContainsKey(key);
+ }
+
+ /// <summary>
+ /// Gets the values.
+ /// </summary>
+ public ICollection<TValue> Values
+ {
+ get { return _dict.Values; }
+ }
}
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/DelegateConverter.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/DelegateConverter.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/DelegateConverter.cs
index ff61e28..0407b62 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/DelegateConverter.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/DelegateConverter.cs
@@ -21,6 +21,7 @@ namespace Apache.Ignite.Core.Impl.Common
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
+ using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Reflection.Emit;
@@ -203,13 +204,16 @@ namespace Apache.Ignite.Core.Impl.Common
/// <typeparam name="T">Result func type.</typeparam>
/// <param name="ctor">Contructor info.</param>
/// <param name="argTypes">Argument types.</param>
- /// <param name="convertResultToObject">if set to <c>true</c> [convert result to object].
+ /// <param name="convertResultToObject">
/// Flag that indicates whether ctor return value should be converted to object.</param>
+ /// <param name="convertParamsFromObject">
+ /// Flag that indicates whether ctor args are object and should be converted to concrete type.</param>
/// <returns>
/// Compiled generic constructor.
/// </returns>
[SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods")]
- public static T CompileCtor<T>(ConstructorInfo ctor, Type[] argTypes, bool convertResultToObject = true)
+ public static T CompileCtor<T>(ConstructorInfo ctor, Type[] argTypes, bool convertResultToObject = true,
+ bool convertParamsFromObject = true)
{
Debug.Assert(ctor != null);
@@ -218,9 +222,16 @@ namespace Apache.Ignite.Core.Impl.Common
for (var i = 0; i < argTypes.Length; i++)
{
- var arg = Expression.Parameter(typeof(object));
- args[i] = arg;
- argsConverted[i] = Expression.Convert(arg, argTypes[i]);
+ if (convertParamsFromObject)
+ {
+ var arg = Expression.Parameter(typeof(object));
+ args[i] = arg;
+ argsConverted[i] = Expression.Convert(arg, argTypes[i]);
+ }
+ else
+ {
+ argsConverted[i] = args[i] = Expression.Parameter(argTypes[i]);
+ }
}
Expression ctorExpr = Expression.New(ctor, argsConverted); // ctor takes args of specific types
@@ -232,6 +243,50 @@ namespace Apache.Ignite.Core.Impl.Common
}
/// <summary>
+ /// Compiles a generic ctor with arbitrary number of arguments
+ /// that takes an uninitialized object as a first arguments.
+ /// </summary>
+ /// <typeparam name="T">Result func type.</typeparam>
+ /// <param name="ctor">Contructor info.</param>
+ /// <param name="argTypes">Argument types.</param>
+ /// <returns>
+ /// Compiled generic constructor.
+ /// </returns>
+ [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods")]
+ public static T CompileUninitializedObjectCtor<T>(ConstructorInfo ctor, Type[] argTypes)
+ {
+ Debug.Assert(ctor != null);
+ Debug.Assert(ctor.DeclaringType != null);
+ Debug.Assert(argTypes != null);
+
+ argTypes = new[] {typeof(object)}.Concat(argTypes).ToArray();
+
+ var helperMethod = new DynamicMethod(string.Empty, typeof(void), argTypes, ctor.Module, true);
+ var il = helperMethod.GetILGenerator();
+
+ il.Emit(OpCodes.Ldarg_0);
+
+ if (ctor.DeclaringType.IsValueType)
+ il.Emit(OpCodes.Unbox, ctor.DeclaringType); // modify boxed copy
+
+ if (argTypes.Length > 1)
+ il.Emit(OpCodes.Ldarg_1);
+
+ if (argTypes.Length > 2)
+ il.Emit(OpCodes.Ldarg_2);
+
+ if (argTypes.Length > 3)
+ throw new NotSupportedException("Not supported: too many ctor args.");
+
+ il.Emit(OpCodes.Call, ctor);
+ il.Emit(OpCodes.Ret);
+
+ var constructorInvoker = helperMethod.CreateDelegate(typeof(T));
+
+ return (T) (object) constructorInvoker;
+ }
+
+ /// <summary>
/// Compiles a generic ctor with arbitrary number of arguments.
/// </summary>
/// <typeparam name="T">Result func type.</typeparam>
@@ -440,5 +495,30 @@ namespace Apache.Ignite.Core.Impl.Common
return method;
}
+
+ /// <summary>
+ /// Gets the constructor with exactly matching signature.
+ /// <para />
+ /// Type.GetConstructor matches compatible ones (i.e. taking object instead of concrete type).
+ /// </summary>
+ /// <param name="type">The type.</param>
+ /// <param name="types">The argument types.</param>
+ /// <returns>Constructor info.</returns>
+ public static ConstructorInfo GetConstructorExact(Type type, Type[] types)
+ {
+ Debug.Assert(type != null);
+ Debug.Assert(types != null);
+
+ foreach (var constructorInfo in type.GetConstructors(
+ BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
+ {
+ var ctorTypes = constructorInfo.GetParameters().Select(x => x.ParameterType);
+
+ if (ctorTypes.SequenceEqual(types))
+ return constructorInfo;
+ }
+
+ return null;
+ }
}
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/DelegateTypeDescriptor.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/DelegateTypeDescriptor.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/DelegateTypeDescriptor.cs
index 2e837c4..4cd0678 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/DelegateTypeDescriptor.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/DelegateTypeDescriptor.cs
@@ -19,7 +19,6 @@ namespace Apache.Ignite.Core.Impl.Common
{
using System;
using System.Globalization;
-
using Apache.Ignite.Core.Cache;
using Apache.Ignite.Core.Cache.Event;
using Apache.Ignite.Core.Compute;
@@ -37,7 +36,7 @@ namespace Apache.Ignite.Core.Impl.Common
/// </summary>
internal class DelegateTypeDescriptor
{
- /** Cached decriptors. */
+ /** Cached descriptors. */
private static readonly CopyOnWriteConcurrentDictionary<Type, DelegateTypeDescriptor> Descriptors
= new CopyOnWriteConcurrentDictionary<Type, DelegateTypeDescriptor>();
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/SerializableTypeDescriptor.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/SerializableTypeDescriptor.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/SerializableTypeDescriptor.cs
new file mode 100644
index 0000000..f16e32a
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/SerializableTypeDescriptor.cs
@@ -0,0 +1,222 @@
+\ufeff/*
+ * 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.Common
+{
+ using System;
+ using System.Diagnostics;
+ using System.Reflection;
+ using System.Runtime.Serialization;
+
+ /// <summary>
+ /// Type descriptor with precompiled delegates to call serialization-related methods.
+ /// </summary>
+ internal class SerializableTypeDescriptor
+ {
+ /** Cached descriptors. */
+ private static readonly CopyOnWriteConcurrentDictionary<Type, SerializableTypeDescriptor> Descriptors
+ = new CopyOnWriteConcurrentDictionary<Type, SerializableTypeDescriptor>();
+
+ /** */
+ private readonly Type _type;
+
+ /** */
+ private readonly Func<SerializationInfo, StreamingContext, object> _serializationCtor;
+
+ /** */
+ private readonly Action<object, SerializationInfo, StreamingContext> _serializationCtorUninitialized;
+
+ /** */
+ private readonly Action<object, StreamingContext> _onSerializing;
+
+ /** */
+ private readonly Action<object, StreamingContext> _onSerialized;
+
+ /** */
+ private readonly Action<object, StreamingContext> _onDeserializing;
+
+ /** */
+ private readonly Action<object, StreamingContext> _onDeserialized;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="SerializableTypeDescriptor"/> class.
+ /// </summary>
+ /// <param name="type">The type.</param>
+ private SerializableTypeDescriptor(Type type)
+ {
+ Debug.Assert(type != null);
+
+ _type = type;
+
+ // Check if there is a serialization ctor.
+ var argTypes = new[] {typeof(SerializationInfo), typeof(StreamingContext)};
+
+ var serializationCtorInfo = DelegateConverter.GetConstructorExact(type, argTypes);
+
+ if (serializationCtorInfo != null)
+ {
+ _serializationCtor = DelegateConverter.CompileCtor<Func<SerializationInfo, StreamingContext, object>>(
+ serializationCtorInfo, argTypes, convertParamsFromObject: false);
+
+ _serializationCtorUninitialized = DelegateConverter.CompileUninitializedObjectCtor<
+ Action<object, SerializationInfo, StreamingContext>>(serializationCtorInfo, argTypes);
+ }
+
+ // Scan methods for callback attributes.
+ // Initialize to empty delegates to avoid null checks.
+ _onSerializing = _onSerialized = _onDeserializing = _onDeserialized = (o, c) => { };
+
+ var baseType = type;
+
+ while (baseType != typeof(object) && baseType != null)
+ {
+ var methods = baseType.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance
+ | BindingFlags.NonPublic | BindingFlags.Public);
+
+ foreach (var method in methods)
+ {
+ if (method.IsDefined(typeof(OnSerializingAttribute), false))
+ {
+ _onSerializing += CompileCallbackMethod(method);
+ }
+
+ if (method.IsDefined(typeof(OnSerializedAttribute), false))
+ {
+ _onSerialized += CompileCallbackMethod(method);
+ }
+
+ if (method.IsDefined(typeof(OnDeserializingAttribute), false))
+ {
+ _onDeserializing += CompileCallbackMethod(method);
+ }
+
+ if (method.IsDefined(typeof(OnDeserializedAttribute), false))
+ {
+ _onDeserialized += CompileCallbackMethod(method);
+ }
+ }
+
+ baseType = baseType.BaseType;
+ }
+ }
+
+ /// <summary>
+ /// Gets the serialization ctor.
+ /// </summary>
+ public Func<SerializationInfo, StreamingContext, object> SerializationCtor
+ {
+ get
+ {
+ if (_serializationCtor == null)
+ throw GetMissingCtorException();
+
+ return _serializationCtor;
+ }
+ }
+
+ /// <summary>
+ /// Gets the serialization ctor to call on an uninitialized instance.
+ /// </summary>
+ public Action<object, SerializationInfo, StreamingContext> SerializationCtorUninitialized
+ {
+ get
+ {
+ if (_serializationCtorUninitialized == null)
+ throw GetMissingCtorException();
+
+ return _serializationCtorUninitialized;
+ }
+ }
+
+ /// <summary>
+ /// Gets the OnSerializing callback action.
+ /// </summary>
+ public Action<object, StreamingContext> OnSerializing
+ {
+ get { return _onSerializing; }
+ }
+
+ /// <summary>
+ /// Gets the OnSerialized callback action.
+ /// </summary>
+ public Action<object, StreamingContext> OnSerialized
+ {
+ get { return _onSerialized; }
+ }
+
+ /// <summary>
+ /// Gets the OnDeserializing callback action.
+ /// </summary>
+ public Action<object, StreamingContext> OnDeserializing
+ {
+ get { return _onDeserializing; }
+ }
+
+ /// <summary>
+ /// Gets the OnDeserialized callback action.
+ /// </summary>
+ public Action<object, StreamingContext> OnDeserialized
+ {
+ get { return _onDeserialized; }
+ }
+
+ /// <summary>
+ /// Gets the <see cref="DelegateTypeDescriptor" /> by type.
+ /// </summary>
+ public static SerializableTypeDescriptor Get(Type type)
+ {
+ SerializableTypeDescriptor result;
+
+ return Descriptors.TryGetValue(type, out result)
+ ? result
+ : Descriptors.GetOrAdd(type, t => new SerializableTypeDescriptor(t));
+ }
+
+ /// <summary>
+ /// Gets the missing ctor exception.
+ /// </summary>
+ private SerializationException GetMissingCtorException()
+ {
+ // Same exception as .NET code throws.
+ return new SerializationException(
+ string.Format("The constructor to deserialize an object of type '{0}' was not found.", _type));
+ }
+
+ /// <summary>
+ /// Checks that callback method has signature "void (StreamingContext)" and compiles it.
+ /// </summary>
+ private static Action<object, StreamingContext> CompileCallbackMethod(MethodInfo method)
+ {
+ Debug.Assert(method != null);
+ Debug.Assert(method.DeclaringType != null);
+
+ var parameters = method.GetParameters();
+
+ if (method.ReturnType != typeof(void) || parameters.Length != 1 ||
+ parameters[0].ParameterType != typeof(StreamingContext))
+ {
+ throw new TypeLoadException(
+ string.Format("Type '{0}' in assembly '{1}' has method '{2}' with an incorrect " +
+ "signature for the serialization attribute that it is decorated with.",
+ method.DeclaringType, method.DeclaringType.Assembly, method.Name));
+ }
+
+ return DelegateConverter.CompileFunc<Action<object, StreamingContext>>(
+ method.DeclaringType, method, new[] {typeof(StreamingContext)}, new[] {false, false});
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Ignite.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Ignite.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Ignite.cs
index f79822d..c38cd95 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Ignite.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Ignite.cs
@@ -157,7 +157,7 @@ namespace Apache.Ignite.Core.Impl
{
if (!string.IsNullOrEmpty(_cfg.SpringConfigUrl))
{
- // If there is a Spring config, use setting from Spring,
+ // If there is a Spring config, use setting from Spring,
// since we ignore .NET config in legacy mode.
var cfg0 = GetConfiguration().BinaryConfiguration;
@@ -424,7 +424,7 @@ namespace Apache.Ignite.Core.Impl
using (var stream = IgniteManager.Memory.Allocate().GetStream())
{
- var writer = Marshaller.StartMarshal(stream);
+ var writer = BinaryUtils.Marshaller.StartMarshal(stream);
configuration.Write(writer);
@@ -463,7 +463,8 @@ namespace Apache.Ignite.Core.Impl
using (var stream = IgniteManager.Memory.Allocate().GetStream())
{
- var writer = Marshaller.StartMarshal(stream);
+ // Use system marshaller: full footers, always unregistered mode.
+ var writer = BinaryUtils.Marshaller.StartMarshal(stream);
configuration.Write(writer);
@@ -639,6 +640,8 @@ namespace Apache.Ignite.Core.Impl
writer.Write(initialValue);
+ Marshaller.FinishMarshal(writer);
+
var memPtr = stream.SynchronizeOutput();
return UU.ProcessorAtomicReference(_proc, name, memPtr, true);
@@ -654,7 +657,7 @@ namespace Apache.Ignite.Core.Impl
stream.SynchronizeInput();
- return new IgniteConfiguration(_marsh.StartUnmarshal(stream), _cfg);
+ return new IgniteConfiguration(BinaryUtils.Marshaller.StartUnmarshal(stream), _cfg);
}
}
@@ -724,7 +727,7 @@ namespace Apache.Ignite.Core.Impl
using (var stream = IgniteManager.Memory.Allocate().GetStream())
{
- var writer = Marshaller.StartMarshal(stream);
+ var writer = BinaryUtils.Marshaller.StartMarshal(stream);
configuration.Write(writer);
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Services/ServiceProxySerializer.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Services/ServiceProxySerializer.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Services/ServiceProxySerializer.cs
index 8e44360..2fd020e 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Services/ServiceProxySerializer.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Services/ServiceProxySerializer.cs
@@ -118,6 +118,8 @@ namespace Apache.Ignite.Core.Impl.Services
var writer = marsh.StartMarshal(stream);
BinaryUtils.WriteInvocationResult(writer, invocationError == null, invocationError ?? methodResult);
+
+ marsh.FinishMarshal(writer);
}
/// <summary>
@@ -182,7 +184,7 @@ namespace Apache.Ignite.Core.Impl.Services
var handler = BinarySystemHandlers.GetWriteHandler(type);
- if (handler != null && !handler.IsSerializable)
+ if (handler != null)
return null;
if (type.IsArray)
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedCallbacks.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedCallbacks.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedCallbacks.cs
index 91ffabb..3028f08 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedCallbacks.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedCallbacks.cs
@@ -376,7 +376,11 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
{
stream.Reset();
- _ignite.Marshaller.StartMarshal(stream).WriteObject(e);
+ var writer = _ignite.Marshaller.StartMarshal(stream);
+
+ writer.WriteObject(e);
+
+ _ignite.Marshaller.FinishMarshal(writer);
return -1;
}
@@ -1164,7 +1168,7 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
{
using (var stream = IgniteManager.Memory.Get(memPtr).GetStream())
{
- var reader = _ignite.Marshaller.StartUnmarshal(stream);
+ var reader = BinaryUtils.Marshaller.StartUnmarshal(stream);
var func = reader.ReadObjectEx<IAffinityFunction>();
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core/NuGet/LINQPad/ComputeExample.linq
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/NuGet/LINQPad/ComputeExample.linq b/modules/platforms/dotnet/Apache.Ignite.Core/NuGet/LINQPad/ComputeExample.linq
index 2ed0493..6886ddb 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/NuGet/LINQPad/ComputeExample.linq
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/NuGet/LINQPad/ComputeExample.linq
@@ -57,7 +57,6 @@ void Main()
/// <summary>
/// Closure counting characters in a string.
/// </summary>
-[Serializable]
public class CharacterCountClosure : IComputeFunc<string, int>
{
/// <summary>
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core/NuGet/LINQPad/PutGetExample.linq
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/NuGet/LINQPad/PutGetExample.linq b/modules/platforms/dotnet/Apache.Ignite.Core/NuGet/LINQPad/PutGetExample.linq
index 7c77d09..ea396da 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/NuGet/LINQPad/PutGetExample.linq
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/NuGet/LINQPad/PutGetExample.linq
@@ -35,11 +35,8 @@ void Main()
// Force new LINQPad query process to reinit JVM
Util.NewProcess = true;
- // Configure cacheable types
- var cfg = new IgniteConfiguration {BinaryConfiguration = new BinaryConfiguration(typeof(Organization))};
-
// Start instance
- using (var ignite = Ignition.Start(cfg))
+ using (var ignite = Ignition.Start())
{
// Create new cache
var cache = ignite.GetOrCreateCache<int, Organization>("orgs");
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core/NuGet/LINQPad/QueryExample.linq
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/NuGet/LINQPad/QueryExample.linq b/modules/platforms/dotnet/Apache.Ignite.Core/NuGet/LINQPad/QueryExample.linq
index 2a2454e..8a7dd10 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/NuGet/LINQPad/QueryExample.linq
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/NuGet/LINQPad/QueryExample.linq
@@ -38,11 +38,8 @@ void Main()
// Force new LINQPad query process to reinit JVM
Util.NewProcess = true;
- // Configure cacheable types
- var cfg = new IgniteConfiguration { BinaryConfiguration = new BinaryConfiguration(typeof(Organization), typeof(Person)) };
-
// Start instance
- using (var ignite = Ignition.Start(cfg))
+ using (var ignite = Ignition.Start())
{
// Create and populate organization cache
var orgs = ignite.GetOrCreateCache<int, Organization>(new CacheConfiguration("orgs-sql",
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Linq/NuGet/LINQPad/QueryExample.linq
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Linq/NuGet/LINQPad/QueryExample.linq b/modules/platforms/dotnet/Apache.Ignite.Linq/NuGet/LINQPad/QueryExample.linq
index 6a28f1f..fb44b12 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Linq/NuGet/LINQPad/QueryExample.linq
+++ b/modules/platforms/dotnet/Apache.Ignite.Linq/NuGet/LINQPad/QueryExample.linq
@@ -39,11 +39,8 @@ void Main()
// Force new LINQPad query process to reinit JVM
Util.NewProcess = true;
- // Configure cacheable types
- var cfg = new IgniteConfiguration { BinaryConfiguration = new BinaryConfiguration(typeof(Organization), typeof(Person)) };
-
// Start instance
- using (var ignite = Ignition.Start(cfg))
+ using (var ignite = Ignition.Start())
{
// Create and populate organization cache
var orgs = ignite.GetOrCreateCache<int, Organization>(new CacheConfiguration("orgs-linq",
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/examples/Apache.Ignite.Examples/App.config
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/examples/Apache.Ignite.Examples/App.config b/modules/platforms/dotnet/examples/Apache.Ignite.Examples/App.config
index 13f0d86..e3bc79d 100644
--- a/modules/platforms/dotnet/examples/Apache.Ignite.Examples/App.config
+++ b/modules/platforms/dotnet/examples/Apache.Ignite.Examples/App.config
@@ -27,22 +27,8 @@
</runtime>
<igniteConfiguration xmlns="http://ignite.apache.org/schema/dotnet/IgniteConfigurationSection">
- <binaryConfiguration>
- <typeConfigurations>
- <binaryTypeConfiguration typeName="Apache.Ignite.ExamplesDll.Binary.OrganizationType" isEnum="true" />
- </typeConfigurations>
- <types>
- <string>Apache.Ignite.ExamplesDll.Binary.Account</string>
- <string>Apache.Ignite.ExamplesDll.Binary.Address</string>
- <string>Apache.Ignite.ExamplesDll.Binary.Employee</string>
- <string>Apache.Ignite.ExamplesDll.Binary.EmployeeKey</string>
- <string>Apache.Ignite.ExamplesDll.Binary.Organization</string>
- <string>Apache.Ignite.ExamplesDll.Compute.AverageSalaryJob</string>
- </types>
- </binaryConfiguration>
-
<atomicConfiguration atomicSequenceReserveSize="10" />
-
+
<discoverySpi type="TcpDiscoverySpi">
<ipFinder type="TcpDiscoveryMulticastIpFinder">
<endpoints>
[3/5] ignite git commit: IGNITE-2703 .NET: Dynamic type registration
Posted by pt...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Examples/ExamplesTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Examples/ExamplesTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Examples/ExamplesTest.cs
index 19e68a6..56a17a3 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Examples/ExamplesTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Examples/ExamplesTest.cs
@@ -131,7 +131,7 @@ namespace Apache.Ignite.Core.Tests.Examples
var proc = new IgniteProcess(args.ToArray());
- Assert.IsTrue(ignite.WaitTopology(2),
+ Assert.IsTrue(ignite.WaitTopology(2),
string.Format("Standalone node failed to join topology: [{0}]", proc.GetInfo()));
Assert.IsTrue(proc.Alive, string.Format("Standalone node stopped unexpectedly: [{0}]",
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ExecutableTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ExecutableTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ExecutableTest.cs
index 636e0fe..0aebd78 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ExecutableTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ExecutableTest.cs
@@ -49,28 +49,6 @@ namespace Apache.Ignite.Core.Tests
private IIgnite _grid;
/// <summary>
- /// Test fixture set-up routine.
- /// </summary>
- [TestFixtureSetUp]
- public void TestFixtureSetUp()
- {
- TestUtils.KillProcesses();
-
- _grid = Ignition.Start(Configuration(SpringCfgPath));
- }
-
- /// <summary>
- /// Test fixture tear-down routine.
- /// </summary>
- [TestFixtureTearDown]
- public void TestFixtureTearDown()
- {
- Ignition.StopAll(true);
-
- TestUtils.KillProcesses();
- }
-
- /// <summary>
/// Set-up routine.
/// </summary>
[SetUp]
@@ -78,6 +56,8 @@ namespace Apache.Ignite.Core.Tests
{
TestUtils.KillProcesses();
+ _grid = Ignition.Start(Configuration(SpringCfgPath));
+
Assert.IsTrue(_grid.WaitTopology(1));
IgniteProcess.SaveConfigurationBackup();
@@ -89,6 +69,10 @@ namespace Apache.Ignite.Core.Tests
[TearDown]
public void TearDown()
{
+ Ignition.StopAll(true);
+
+ TestUtils.KillProcesses();
+
IgniteProcess.RestoreConfigurationBackup();
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core.Tests/SerializationTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/SerializationTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/SerializationTest.cs
deleted file mode 100644
index 2812468..0000000
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/SerializationTest.cs
+++ /dev/null
@@ -1,240 +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.Tests
-{
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Reflection;
- using System.Reflection.Emit;
- using System.Runtime.Serialization;
- using System.Xml;
- using Apache.Ignite.Core.Cluster;
- using Apache.Ignite.Core.Compute;
- using Apache.Ignite.Core.Impl;
- using NUnit.Framework;
-
- /// <summary>
- /// Tests for native serialization.
- /// </summary>
- public class SerializationTest
- {
- /** Grid name. */
- private const string GridName = "SerializationTest";
-
- /// <summary>
- /// Set up routine.
- /// </summary>
- [TestFixtureSetUp]
- public void SetUp()
- {
- var cfg = new IgniteConfiguration
- {
- IgniteInstanceName = GridName,
- JvmClasspath = TestUtils.CreateTestClasspath(),
- JvmOptions = TestUtils.TestJavaOptions(),
- SpringConfigUrl = "config\\native-client-test-cache.xml"
- };
-
- Ignition.Start(cfg);
- }
-
- /// <summary>
- /// Tear down routine.
- /// </summary>
- [TestFixtureTearDown]
- public void TearDown()
- {
- Ignition.StopAll(true);
- }
-
- /// <summary>
- /// Test complex file serialization.
- /// </summary>
- [Test]
- public void TestSerializableXmlDoc()
- {
- var grid = Ignition.GetIgnite(GridName);
- var cache = grid.GetCache<int, SerializableXmlDoc>("replicated");
-
- var doc = new SerializableXmlDoc();
-
- doc.LoadXml("<document><test1>val</test1><test2 attr=\"x\" /></document>");
-
- for (var i = 0; i < 50; i++)
- {
- // Test cache
- cache.Put(i, doc);
-
- var resultDoc = cache.Get(i);
-
- Assert.AreEqual(doc.OuterXml, resultDoc.OuterXml);
-
- // Test task with document arg
- CheckTask(grid, doc);
- }
- }
-
- /// <summary>
- /// Checks task execution.
- /// </summary>
- /// <param name="grid">Grid.</param>
- /// <param name="arg">Task arg.</param>
- private static void CheckTask(IIgnite grid, object arg)
- {
- var jobResult = grid.GetCompute().Execute(new CombineStringsTask(), arg);
-
- var nodeCount = grid.GetCluster().GetNodes().Count;
-
- var expectedRes =
- CombineStringsTask.CombineStrings(Enumerable.Range(0, nodeCount).Select(x => arg.ToString()));
-
- Assert.AreEqual(expectedRes, jobResult.InnerXml);
- }
-
- /// <summary>
- /// Tests custom serialization binder.
- /// </summary>
- [Test]
- public void TestSerializationBinder()
- {
- const int count = 50;
-
- var cache = Ignition.GetIgnite(GridName).GetCache<int, object>("local");
-
- // Put multiple objects from muliple same-named assemblies to cache
- for (var i = 0; i < count; i++)
- {
- dynamic val = Activator.CreateInstance(GenerateDynamicType());
-
- val.Id = i;
- val.Name = "Name_" + i;
-
- cache.Put(i, val);
- }
-
- // Verify correct deserialization
- for (var i = 0; i < count; i++)
- {
- dynamic val = cache.Get(i);
-
- Assert.AreEqual(val.Id, i);
- Assert.AreEqual(val.Name, "Name_" + i);
- }
- }
-
- /// <summary>
- /// Generates a Type in runtime, puts it into a dynamic assembly.
- /// </summary>
- /// <returns></returns>
- public static Type GenerateDynamicType()
- {
- var asmBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(
- new AssemblyName("GridSerializationTestDynamicAssembly"), AssemblyBuilderAccess.Run);
-
- var moduleBuilder = asmBuilder.DefineDynamicModule("GridSerializationTestDynamicModule");
-
- var typeBuilder = moduleBuilder.DefineType("GridSerializationTestDynamicType",
- TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.Serializable);
-
- typeBuilder.DefineField("Id", typeof (int), FieldAttributes.Public);
-
- typeBuilder.DefineField("Name", typeof (string), FieldAttributes.Public);
-
- return typeBuilder.CreateType();
- }
- }
-
- [Serializable]
- [DataContract]
- public sealed class SerializableXmlDoc : XmlDocument, ISerializable
- {
- /// <summary>
- /// Default ctor.
- /// </summary>
- public SerializableXmlDoc()
- {
- // No-op
- }
-
- /// <summary>
- /// Serialization ctor.
- /// </summary>
- private SerializableXmlDoc(SerializationInfo info, StreamingContext context)
- {
- LoadXml(info.GetString("xmlDocument"));
- }
-
- /** <inheritdoc /> */
- public void GetObjectData(SerializationInfo info, StreamingContext context)
- {
- info.AddValue("xmlDocument", OuterXml, typeof(string));
- }
- }
-
- [Serializable]
- public class CombineStringsTask : IComputeTask<object, string, SerializableXmlDoc>
- {
- public IDictionary<IComputeJob<string>, IClusterNode> Map(IList<IClusterNode> subgrid, object arg)
- {
- return subgrid.ToDictionary(x => (IComputeJob<string>) new ToStringJob {Arg = arg}, x => x);
- }
-
- public ComputeJobResultPolicy OnResult(IComputeJobResult<string> res, IList<IComputeJobResult<string>> rcvd)
- {
- return ComputeJobResultPolicy.Wait;
- }
-
- public SerializableXmlDoc Reduce(IList<IComputeJobResult<string>> results)
- {
- var result = new SerializableXmlDoc();
-
- result.LoadXml(CombineStrings(results.Select(x => x.Data)));
-
- return result;
- }
-
- public static string CombineStrings(IEnumerable<string> strings)
- {
- var text = string.Concat(strings.Select(x => string.Format("<val>{0}</val>", x)));
-
- return string.Format("<document>{0}</document>", text);
- }
- }
-
- [Serializable]
- public class ToStringJob : IComputeJob<string>
- {
- /// <summary>
- /// Job argument.
- /// </summary>
- public object Arg { get; set; }
-
- /** <inheritdoc /> */
- public string Execute()
- {
- return Arg.ToString();
- }
-
- /** <inheritdoc /> */
- public void Cancel()
- {
- // No-op.
- }
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Services/ServiceProxyTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Services/ServiceProxyTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Services/ServiceProxyTest.cs
index dcb5393..eb6192d 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Services/ServiceProxyTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Services/ServiceProxyTest.cs
@@ -110,8 +110,13 @@ namespace Apache.Ignite.Core.Tests.Services
Assert.IsNull(_svc.ObjProp);
prx.ObjProp = new TestClass {Prop = "prop2"};
- Assert.AreEqual("prop2", ((TestClass)prx.ObjProp).Prop);
- Assert.AreEqual("prop2", ((TestClass)_svc.ObjProp).Prop);
+
+ var propVal = KeepBinary
+ ? ((IBinaryObject) prx.ObjProp).Deserialize<TestClass>().Prop
+ : ((TestClass) prx.ObjProp).Prop;
+
+ Assert.AreEqual("prop2", propVal);
+ Assert.AreEqual("prop2", ((TestClass) _svc.ObjProp).Prop);
}
/// <summary>
@@ -191,10 +196,19 @@ namespace Apache.Ignite.Core.Tests.Services
var prx = GetProxy();
var err = Assert.Throws<ServiceInvocationException>(prx.ExceptionMethod);
- Assert.AreEqual("Expected exception", err.InnerException.Message);
- var ex = Assert.Throws<ServiceInvocationException>(() => prx.CustomExceptionMethod());
- Assert.IsTrue(ex.ToString().Contains("+CustomException"));
+ if (KeepBinary)
+ {
+ Assert.IsNotNull(err.BinaryCause);
+ Assert.AreEqual("Expected exception", err.BinaryCause.Deserialize<Exception>().Message);
+ }
+ else
+ {
+ Assert.IsNotNull(err.InnerException);
+ Assert.AreEqual("Expected exception", err.InnerException.Message);
+ }
+
+ Assert.Throws<ServiceInvocationException>(() => prx.CustomExceptionMethod());
}
[Test]
@@ -243,7 +257,7 @@ namespace Apache.Ignite.Core.Tests.Services
/// <summary>
/// Creates the proxy.
/// </summary>
- protected T GetProxy<T>()
+ private T GetProxy<T>()
{
_svc = new TestIgniteService(Binary);
@@ -591,9 +605,19 @@ namespace Apache.Ignite.Core.Tests.Services
/// <summary>
/// Custom non-serializable exception.
/// </summary>
- private class CustomException : Exception
+ private class CustomException : Exception, IBinarizable
{
-
+ /** <inheritDoc /> */
+ public void WriteBinary(IBinaryWriter writer)
+ {
+ throw new BinaryObjectException("Expected");
+ }
+
+ /** <inheritDoc /> */
+ public void ReadBinary(IBinaryReader reader)
+ {
+ throw new BinaryObjectException("Expected");
+ }
}
/// <summary>
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestUtils.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestUtils.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestUtils.cs
index 8360bf1..0bb3b7f 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestUtils.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestUtils.cs
@@ -27,6 +27,7 @@ namespace Apache.Ignite.Core.Tests
using Apache.Ignite.Core.Discovery.Tcp;
using Apache.Ignite.Core.Discovery.Tcp.Static;
using Apache.Ignite.Core.Impl;
+ using Apache.Ignite.Core.Impl.Binary;
using Apache.Ignite.Core.Impl.Common;
using Apache.Ignite.Core.Tests.Process;
using NUnit.Framework;
@@ -370,5 +371,15 @@ namespace Apache.Ignite.Core.Tests
Assert.IsTrue(proc.WaitForExit(15000));
Assert.AreEqual(0, proc.ExitCode);
}
+
+ /// <summary>
+ /// Serializes and deserializes back an object.
+ /// </summary>
+ public static T SerializeDeserialize<T>(T obj)
+ {
+ var marsh = new Marshaller(null) {CompactFooter = false};
+
+ return marsh.Unmarshal<T>(marsh.Marshal(obj));
+ }
}
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/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 333b9bc..2a174eb 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
@@ -186,11 +186,12 @@
<Compile Include="Common\IgniteFutureCancelledException.cs" />
<Compile Include="Common\IgniteGuid.cs" />
<Compile Include="Common\Package-Info.cs" />
- <Compile Include="Impl\Binary\DateTimeSerializer.cs" />
<Compile Include="Impl\Binary\IO\IBinaryStreamProcessor.cs" />
<Compile Include="Impl\Binary\Metadata\BinaryField.cs" />
<Compile Include="Impl\Binary\SerializableSerializer.cs" />
<Compile Include="Impl\Binary\BinaryWriterExtensions.cs" />
+ <Compile Include="Impl\Binary\DeserializationCallbackProcessor.cs" />
+ <Compile Include="Impl\Binary\ReflectionUtils.cs" />
<Compile Include="Cache\Affinity\AffinityFunctionBase.cs" />
<Compile Include="Impl\Cache\Store\CacheStore.cs" />
<Compile Include="Impl\Cache\Store\ICacheStoreInternal.cs" />
@@ -319,6 +320,7 @@
<Compile Include="Impl\Common\CopyOnWriteConcurrentDictionary.cs" />
<Compile Include="Impl\Common\DelegateConverter.cs" />
<Compile Include="Impl\Common\DelegateTypeDescriptor.cs" />
+ <Compile Include="Impl\Common\SerializableTypeDescriptor.cs" />
<Compile Include="Impl\Events\EventTypeConverter.cs" />
<Compile Include="Impl\Common\Fnv1Hash.cs" />
<Compile Include="Impl\Common\Future.cs" />
@@ -385,11 +387,9 @@
<Compile Include="Impl\Messaging\MessageListenerHolder.cs" />
<Compile Include="Impl\Messaging\Messaging.cs" />
<Compile Include="Impl\NativeMethods.cs" />
- <Compile Include="Impl\Binary\DateTimeHolder.cs" />
<Compile Include="Impl\Binary\IO\IBinaryStream.cs" />
<Compile Include="Impl\Binary\IO\BinaryStreamBase.cs" />
<Compile Include="Impl\Binary\IO\BinaryHeapStream.cs" />
- <Compile Include="Impl\Binary\IO\BinaryStreamAdapter.cs" />
<Compile Include="Impl\Binary\IBinaryTypeDescriptor.cs" />
<Compile Include="Impl\Binary\IBinaryWriteAware.cs" />
<Compile Include="Impl\Binary\Metadata\IBinaryTypeHandler.cs" />
@@ -419,7 +419,6 @@
<Compile Include="Impl\Binary\BinaryObject.cs" />
<Compile Include="Impl\Binary\BinaryUtils.cs" />
<Compile Include="Impl\Binary\BinaryWriter.cs" />
- <Compile Include="Impl\Binary\SerializableObjectHolder.cs" />
<Compile Include="Impl\Binary\Structure\BinaryStructure.cs" />
<Compile Include="Impl\Binary\Structure\BinaryStructureEntry.cs" />
<Compile Include="Impl\Binary\Structure\BinaryStructureJumpTable.cs" />
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/CacheConfiguration.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/CacheConfiguration.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/CacheConfiguration.cs
index 29d2ee3..4f48ea5 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/CacheConfiguration.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/CacheConfiguration.cs
@@ -235,6 +235,9 @@ namespace Apache.Ignite.Core.Cache.Configuration
/// <param name="reader">The reader.</param>
internal CacheConfiguration(IBinaryRawReader reader)
{
+ // Make sure system marshaller is used.
+ Debug.Assert(((BinaryReader) reader).Marshaller == BinaryUtils.Marshaller);
+
AtomicityMode = (CacheAtomicityMode) reader.ReadInt();
AtomicWriteOrderMode = (CacheAtomicWriteOrderMode) reader.ReadInt();
Backups = reader.ReadInt();
@@ -297,6 +300,9 @@ namespace Apache.Ignite.Core.Cache.Configuration
/// <param name="writer">The writer.</param>
internal void Write(IBinaryRawWriter writer)
{
+ // Make sure system marshaller is used.
+ Debug.Assert(((BinaryWriter) writer).Marshaller == BinaryUtils.Marshaller);
+
writer.WriteInt((int) AtomicityMode);
writer.WriteInt((int) AtomicWriteOrderMode);
writer.WriteInt(Backups);
@@ -740,7 +746,7 @@ namespace Apache.Ignite.Core.Cache.Configuration
public IAffinityFunction AffinityFunction { get; set; }
/// <summary>
- /// Gets or sets the factory for <see cref="IExpiryPolicy"/> to be used for all cache operations,
+ /// Gets or sets the factory for <see cref="IExpiryPolicy"/> to be used for all cache operations,
/// unless <see cref="ICache{TK,TV}.WithExpiryPolicy"/> is called.
/// <para />
/// Default is null, which means no expiration.
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfiguration.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfiguration.cs b/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfiguration.cs
index d3bd50c..28842e9 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfiguration.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfiguration.cs
@@ -159,7 +159,7 @@
using (var stream = IgniteManager.Memory.Allocate().GetStream())
{
- var marsh = new Marshaller(configuration.BinaryConfiguration);
+ var marsh = BinaryUtils.Marshaller;
configuration.Write(marsh.StartMarshal(stream));
@@ -276,15 +276,26 @@
// Send only descriptors with non-null EqualityComparer to preserve old behavior where
// remote nodes can have no BinaryConfiguration.
- var types = writer.Marshaller.GetUserTypeDescriptors().Where(x => x.EqualityComparer != null).ToList();
- writer.WriteInt(types.Count);
+ if (BinaryConfiguration.TypeConfigurations != null &&
+ BinaryConfiguration.TypeConfigurations.Any(x => x.EqualityComparer != null))
+ {
+ // Create a new marshaller to reuse type name resolver mechanism.
+ var types = new Marshaller(BinaryConfiguration).GetUserTypeDescriptors()
+ .Where(x => x.EqualityComparer != null).ToList();
+
+ writer.WriteInt(types.Count);
- foreach (var type in types)
+ foreach (var type in types)
+ {
+ writer.WriteString(BinaryUtils.SimpleTypeName(type.TypeName));
+ writer.WriteBoolean(type.IsEnum);
+ BinaryEqualityComparerSerializer.Write(writer, type.EqualityComparer);
+ }
+ }
+ else
{
- writer.WriteString(BinaryUtils.SimpleTypeName(type.TypeName));
- writer.WriteBoolean(type.IsEnum);
- BinaryEqualityComparerSerializer.Write(writer, type.EqualityComparer);
+ writer.WriteInt(0);
}
}
else
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core/Ignition.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Ignition.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Ignition.cs
index 1190c14..f590794 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Ignition.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Ignition.cs
@@ -359,11 +359,11 @@ namespace Apache.Ignite.Core
if (cfg.BinaryConfiguration == null)
cfg.BinaryConfiguration = binaryCfg;
- _startup.Marshaller = new Marshaller(cfg.BinaryConfiguration);
+ _startup.Marshaller = new Marshaller(cfg.BinaryConfiguration, log);
// 3. Send configuration details to Java
cfg.Validate(log);
- cfg.Write(_startup.Marshaller.StartMarshal(outStream));
+ cfg.Write(BinaryUtils.Marshaller.StartMarshal(outStream)); // Use system marshaller.
}
/// <summary>
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarizableSerializer.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarizableSerializer.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarizableSerializer.cs
index dcb261f..2273a93 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarizableSerializer.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarizableSerializer.cs
@@ -17,7 +17,6 @@
namespace Apache.Ignite.Core.Impl.Binary
{
- using System;
using System.Runtime.Serialization;
using Apache.Ignite.Core.Binary;
@@ -39,9 +38,9 @@ namespace Apache.Ignite.Core.Impl.Binary
}
/** <inheritdoc /> */
- public T ReadBinary<T>(BinaryReader reader, Type type, int pos)
+ public T ReadBinary<T>(BinaryReader reader, IBinaryTypeDescriptor desc, int pos)
{
- var obj = (T) FormatterServices.GetUninitializedObject(type);
+ var obj = (T) FormatterServices.GetUninitializedObject(desc.Type);
reader.AddHandle(pos, obj);
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryFullTypeDescriptor.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryFullTypeDescriptor.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryFullTypeDescriptor.cs
index d88e7a9..6a911ad 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryFullTypeDescriptor.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryFullTypeDescriptor.cs
@@ -62,7 +62,7 @@ namespace Apache.Ignite.Core.Impl.Binary
private volatile BinaryStructure _readerTypeStructure = BinaryStructure.CreateEmpty();
/** Type schema. */
- private readonly BinaryObjectSchema _schema = new BinaryObjectSchema();
+ private readonly BinaryObjectSchema _schema;
/** Enum flag. */
private readonly bool _isEnum;
@@ -70,6 +70,9 @@ namespace Apache.Ignite.Core.Impl.Binary
/** Comparer. */
private readonly IBinaryEqualityComparer _equalityComparer;
+ /** Register flag. */
+ private readonly bool _isRegistered;
+
/// <summary>
/// Constructor.
/// </summary>
@@ -84,6 +87,7 @@ namespace Apache.Ignite.Core.Impl.Binary
/// <param name="affKeyFieldName">Affinity field key name.</param>
/// <param name="isEnum">Enum flag.</param>
/// <param name="comparer">Equality comparer.</param>
+ /// <param name="isRegistered">Registered flag.</param>
public BinaryFullTypeDescriptor(
Type type,
int typeId,
@@ -94,8 +98,9 @@ namespace Apache.Ignite.Core.Impl.Binary
IBinarySerializerInternal serializer,
bool keepDeserialized,
string affKeyFieldName,
- bool isEnum,
- IEqualityComparer<IBinaryObject> comparer)
+ bool isEnum,
+ IEqualityComparer<IBinaryObject> comparer,
+ bool isRegistered = true)
{
_type = type;
_typeId = typeId;
@@ -114,6 +119,38 @@ namespace Apache.Ignite.Core.Impl.Binary
throw new IgniteException(string.Format("Unsupported IEqualityComparer<IBinaryObject> " +
"implementation: {0}. Only predefined implementations " +
"are supported.", comparer.GetType()));
+
+ _isRegistered = isRegistered;
+ _schema = new BinaryObjectSchema();
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="BinaryFullTypeDescriptor"/> class,
+ /// copying values from specified descriptor.
+ /// </summary>
+ /// <param name="desc">The descriptor to copy from.</param>
+ /// <param name="type">Type.</param>
+ /// <param name="serializer">Serializer.</param>
+ /// <param name="isRegistered">Registered flag.</param>
+ public BinaryFullTypeDescriptor(BinaryFullTypeDescriptor desc, Type type,
+ IBinarySerializerInternal serializer, bool isRegistered)
+ {
+ _type = type;
+ _typeId = desc._typeId;
+ _typeName = desc._typeName;
+ _userType = desc._userType;
+ _nameMapper = desc._nameMapper;
+ _idMapper = desc._idMapper;
+ _serializer = serializer;
+ _keepDeserialized = desc._keepDeserialized;
+ _affKeyFieldName = desc._affKeyFieldName;
+ _isEnum = desc._isEnum;
+ _equalityComparer = desc._equalityComparer;
+ _isRegistered = isRegistered;
+
+ _schema = desc._schema;
+ _writerTypeStruct = desc._writerTypeStruct;
+ _readerTypeStructure = desc._readerTypeStructure;
}
/// <summary>
@@ -237,5 +274,11 @@ namespace Apache.Ignite.Core.Impl.Binary
{
get { return _schema; }
}
+
+ /** <inheritDoc /> */
+ public bool IsRegistered
+ {
+ get { return _isRegistered; }
+ }
}
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObjectBuilder.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObjectBuilder.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObjectBuilder.cs
index e77cbae..e4fb10a 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObjectBuilder.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObjectBuilder.cs
@@ -676,6 +676,9 @@ namespace Apache.Ignite.Core.Impl.Binary
? BinaryObjectHeader.Flag.UserType
: BinaryObjectHeader.Flag.None;
+ if (inHeader.IsCustomDotNetType)
+ flags |= BinaryObjectHeader.Flag.CustomDotNetType;
+
// Write raw data.
int outRawOff = outStream.Position - outStartPos;
@@ -936,8 +939,6 @@ namespace Apache.Ignite.Core.Impl.Binary
case BinaryUtils.TypeArrayString:
case BinaryUtils.TypeArrayGuid:
case BinaryUtils.TypeArrayTimestamp:
- case BinaryUtils.TypeArrayEnum:
- case BinaryUtils.TypeArray:
int arrLen = inStream.ReadInt();
outStream.WriteInt(arrLen);
@@ -947,6 +948,28 @@ namespace Apache.Ignite.Core.Impl.Binary
break;
+ case BinaryUtils.TypeArrayEnum:
+ case BinaryUtils.TypeArray:
+ int type = inStream.ReadInt();
+
+ outStream.WriteInt(type);
+
+ if (type == BinaryUtils.TypeUnregistered)
+ {
+ outStream.WriteByte(inStream.ReadByte()); // String header.
+
+ BinaryUtils.WriteString(BinaryUtils.ReadString(inStream), outStream); // String data.
+ }
+
+ arrLen = inStream.ReadInt();
+
+ outStream.WriteInt(arrLen);
+
+ for (int i = 0; i < arrLen; i++)
+ Mutate0(ctx, inStream, outStream, false, EmptyVals);
+
+ break;
+
case BinaryUtils.TypeCollection:
int colLen = inStream.ReadInt();
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObjectHeader.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObjectHeader.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObjectHeader.cs
index 636b177..0f0fafe 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObjectHeader.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObjectHeader.cs
@@ -58,7 +58,10 @@ namespace Apache.Ignite.Core.Impl.Binary
OffsetTwoBytes = 0x10,
/** Flag: compact footer, no field IDs. */
- CompactFooter = 0x20
+ CompactFooter = 0x20,
+
+ /** Flag: raw data contains .NET type information. */
+ CustomDotNetType = 0x40
}
/** Actual header layout */
@@ -164,6 +167,14 @@ namespace Apache.Ignite.Core.Impl.Binary
}
/// <summary>
+ /// Gets the custom .NET type flag.
+ /// </summary>
+ public bool IsCustomDotNetType
+ {
+ get { return (Flags & Flag.CustomDotNetType) == Flag.CustomDotNetType; }
+ }
+
+ /// <summary>
/// Gets the size of the schema field offset (1, 2 or 4 bytes).
/// </summary>
public int SchemaFieldOffsetSize
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObjectSchemaSerializer.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObjectSchemaSerializer.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObjectSchemaSerializer.cs
index f1d2f6a..e2f9ea7 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObjectSchemaSerializer.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObjectSchemaSerializer.cs
@@ -249,6 +249,8 @@ namespace Apache.Ignite.Core.Impl.Binary
if (fieldIds == null)
{
+ Debug.Assert(hdr.TypeId != BinaryUtils.TypeUnregistered);
+
if (marsh.Ignite != null)
fieldIds = marsh.Ignite.BinaryProcessor.GetSchema(hdr.TypeId, hdr.SchemaId);
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryProcessor.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryProcessor.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryProcessor.cs
index f5bc370..555a042 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryProcessor.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryProcessor.cs
@@ -17,6 +17,7 @@
namespace Apache.Ignite.Core.Impl.Binary
{
+ using System;
using System.Collections.Generic;
using System.Diagnostics;
using Apache.Ignite.Core.Binary;
@@ -36,7 +37,9 @@ namespace Apache.Ignite.Core.Impl.Binary
GetMeta = 1,
GetAllMeta = 2,
PutMeta = 3,
- GetSchema = 4
+ GetSchema = 4,
+ RegisterType = 5,
+ GetType = 6
}
/// <summary>
@@ -101,7 +104,7 @@ namespace Apache.Ignite.Core.Impl.Binary
/// Put binary types to Grid.
/// </summary>
/// <param name="types">Binary types.</param>
- internal void PutBinaryTypes(ICollection<BinaryType> types)
+ public void PutBinaryTypes(ICollection<BinaryType> types)
{
DoOutOp((int) Op.PutMeta, w =>
{
@@ -153,5 +156,36 @@ namespace Apache.Ignite.Core.Impl.Binary
Marshaller.OnBinaryTypesSent(types);
}
+
+ /// <summary>
+ /// Registers the type.
+ /// </summary>
+ /// <param name="id">The identifier.</param>
+ /// <param name="type">The type.</param>
+ /// <returns>True if registration succeeded; otherwise, false.</returns>
+ public bool RegisterType(int id, Type type)
+ {
+ Debug.Assert(type != null);
+ Debug.Assert(id != BinaryUtils.TypeUnregistered);
+
+ return DoOutOp((int) Op.RegisterType, w =>
+ {
+ w.WriteInt(id);
+ w.WriteString(type.AssemblyQualifiedName);
+ }) == True;
+ }
+
+ /// <summary>
+ /// Gets the type by id.
+ /// </summary>
+ /// <param name="id">The identifier.</param>
+ /// <returns>Type or null.</returns>
+ public Type GetType(int id)
+ {
+ var typeName = DoOutInOp((int) Op.GetType, w => w.WriteInt(id),
+ r => Marshaller.StartUnmarshal(r).ReadString());
+
+ return new TypeResolver().ResolveType(typeName);
+ }
}
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReader.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReader.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReader.cs
index 092eb72..49bab77 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReader.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReader.cs
@@ -20,6 +20,7 @@ namespace Apache.Ignite.Core.Impl.Binary
using System;
using System.Collections;
using System.Collections.Generic;
+ using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using Apache.Ignite.Core.Binary;
@@ -79,6 +80,14 @@ namespace Apache.Ignite.Core.Impl.Binary
get { return _marsh; }
}
+ /// <summary>
+ /// Gets the mode.
+ /// </summary>
+ public BinaryMode Mode
+ {
+ get { return _mode; }
+ }
+
/** <inheritdoc /> */
public IBinaryRawReader GetRawReader()
{
@@ -572,6 +581,14 @@ namespace Apache.Ignite.Core.Impl.Binary
throw new BinaryObjectException("Invalid header on deserialization [pos=" + pos + ", hdr=" + hdr + ']');
}
+
+ /// <summary>
+ /// Gets the flag indicating that there is custom type information in raw region.
+ /// </summary>
+ public bool GetCustomTypeDataFlag()
+ {
+ return _frame.Hdr.IsCustomDotNetType;
+ }
/// <summary>
/// Reads the binary object.
@@ -676,7 +693,9 @@ namespace Apache.Ignite.Core.Impl.Binary
else
{
// Find descriptor.
- var desc = _marsh.GetDescriptor(hdr.IsUserType, hdr.TypeId);
+ var desc = hdr.TypeId == BinaryUtils.TypeUnregistered
+ ? _marsh.GetDescriptor(Type.GetType(ReadString(), true))
+ : _marsh.GetDescriptor(hdr.IsUserType, hdr.TypeId, true);
// Instantiate object.
if (desc.Type == null)
@@ -707,7 +726,7 @@ namespace Apache.Ignite.Core.Impl.Binary
_frame.Raw = false;
// Read object.
- var obj = desc.Serializer.ReadBinary<T>(this, desc.Type, pos);
+ var obj = desc.Serializer.ReadBinary<T>(this, desc, pos);
_frame.Struct.UpdateReaderStructure();
@@ -758,8 +777,10 @@ namespace Apache.Ignite.Core.Impl.Binary
// Get schema from Java
var ignite = Marshaller.Ignite;
- var schema = ignite == null
- ? null
+ Debug.Assert(typeId != BinaryUtils.TypeUnregistered);
+
+ var schema = ignite == null
+ ? null
: ignite.BinaryProcessor.GetSchema(_frame.Hdr.TypeId, _frame.Hdr.SchemaId);
if (schema == null)
@@ -850,6 +871,14 @@ namespace Apache.Ignite.Core.Impl.Binary
}
/// <summary>
+ /// Seeks to raw data.
+ /// </summary>
+ internal void SeekToRaw()
+ {
+ Stream.Seek(_frame.Pos + _frame.Hdr.GetRawOffset(Stream, _frame.Pos), SeekOrigin.Begin);
+ }
+
+ /// <summary>
/// Mark current output as raw.
/// </summary>
private void MarkRaw()
@@ -858,7 +887,7 @@ namespace Apache.Ignite.Core.Impl.Binary
{
_frame.Raw = true;
- Stream.Seek(_frame.Pos + _frame.Hdr.GetRawOffset(Stream, _frame.Pos), SeekOrigin.Begin);
+ SeekToRaw();
}
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/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 795f8ac..907b465 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReflectiveActions.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReflectiveActions.cs
@@ -722,7 +722,7 @@ namespace Apache.Ignite.Core.Impl.Binary
// Assign field value
var targetParam = Expression.Parameter(typeof(object));
- var targetParamConverted = Expression.Convert(targetParam, field.DeclaringType);
+ var targetParamConverted = Expression.Convert(targetParam, typeof(object));
var assignExpr = Expression.Call(DelegateConverter.GetWriteFieldMethod(field), targetParamConverted,
readExpr);
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReflectiveSerializerInternal.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReflectiveSerializerInternal.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReflectiveSerializerInternal.cs
index c9fd3cc..e160559 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReflectiveSerializerInternal.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReflectiveSerializerInternal.cs
@@ -20,19 +20,17 @@ namespace Apache.Ignite.Core.Impl.Binary
using System;
using System.Collections.Generic;
using System.Diagnostics;
+ using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using Apache.Ignite.Core.Binary;
+ using Apache.Ignite.Core.Impl.Common;
/// <summary>
/// Internal reflective serializer.
/// </summary>
internal sealed class BinaryReflectiveSerializerInternal : IBinarySerializerInternal
{
- /** Cached binding flags. */
- private const BindingFlags Flags = BindingFlags.Instance | BindingFlags.Public |
- BindingFlags.NonPublic | BindingFlags.DeclaredOnly;
-
/** Raw mode flag. */
private readonly bool _rawMode;
@@ -42,6 +40,9 @@ namespace Apache.Ignite.Core.Impl.Binary
/** Read actions to be performed. */
private readonly BinaryReflectiveReadAction[] _rActions;
+ /** Callback type descriptor. */
+ private readonly SerializableTypeDescriptor _serializableDescriptor;
+
/// <summary>
/// Initializes a new instance of the <see cref="BinaryReflectiveSerializer"/> class.
/// </summary>
@@ -53,36 +54,64 @@ namespace Apache.Ignite.Core.Impl.Binary
/// <summary>
/// Initializes a new instance of the <see cref="BinaryReflectiveSerializer"/> class.
/// </summary>
- private BinaryReflectiveSerializerInternal(BinaryReflectiveWriteAction[] wActions, BinaryReflectiveReadAction[] rActions, bool raw)
+ private BinaryReflectiveSerializerInternal(BinaryReflectiveWriteAction[] wActions,
+ BinaryReflectiveReadAction[] rActions, bool raw, SerializableTypeDescriptor serializableDescriptor)
{
Debug.Assert(wActions != null);
Debug.Assert(rActions != null);
+ Debug.Assert(serializableDescriptor != null);
_wActions = wActions;
_rActions = rActions;
_rawMode = raw;
+ _serializableDescriptor = serializableDescriptor;
}
/** <inheritdoc /> */
void IBinarySerializerInternal.WriteBinary<T>(T obj, BinaryWriter writer)
{
Debug.Assert(_wActions != null);
+ Debug.Assert(writer != null);
+
+ var ctx = GetStreamingContext(writer);
+
+ _serializableDescriptor.OnSerializing(obj, ctx);
foreach (var action in _wActions)
action(obj, writer);
+
+ _serializableDescriptor.OnSerialized(obj, ctx);
}
/** <inheritdoc /> */
- T IBinarySerializerInternal.ReadBinary<T>(BinaryReader reader, Type type, int pos)
+ T IBinarySerializerInternal.ReadBinary<T>(BinaryReader reader, IBinaryTypeDescriptor desc, int pos)
{
Debug.Assert(_rActions != null);
+ Debug.Assert(reader != null);
+ Debug.Assert(desc != null);
+
+ var obj = FormatterServices.GetUninitializedObject(desc.Type);
+
+ var ctx = GetStreamingContext(reader);
+
+ _serializableDescriptor.OnDeserializing(obj, ctx);
- var obj = FormatterServices.GetUninitializedObject(type);
+ DeserializationCallbackProcessor.Push(obj);
- reader.AddHandle(pos, obj);
+ try
+ {
+ reader.AddHandle(pos, obj);
+
+ foreach (var action in _rActions)
+ action(obj, reader);
- foreach (var action in _rActions)
- action(obj, reader);
+ _serializableDescriptor.OnDeserialized(obj, ctx);
+
+ }
+ finally
+ {
+ DeserializationCallbackProcessor.Pop();
+ }
return (T) obj;
}
@@ -103,20 +132,7 @@ namespace Apache.Ignite.Core.Impl.Binary
{
Debug.Assert(_wActions == null && _rActions == null);
- 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;
- }
+ var fields = ReflectionUtils.GetAllFields(type).Where(x => !x.IsNotSerialized).ToList();
IDictionary<int, string> idMap = new Dictionary<int, string>();
@@ -152,7 +168,9 @@ namespace Apache.Ignite.Core.Impl.Binary
rActions[i] = readAction;
}
- return new BinaryReflectiveSerializerInternal(wActions, rActions, _rawMode);
+ var serDesc = SerializableTypeDescriptor.Get(type);
+
+ return new BinaryReflectiveSerializerInternal(wActions, rActions, _rawMode, serDesc);
}
/// <summary>
@@ -165,5 +183,21 @@ namespace Apache.Ignite.Core.Impl.Binary
return string.Compare(name1, name2, StringComparison.OrdinalIgnoreCase);
}
+
+ /// <summary>
+ /// Gets the streaming context.
+ /// </summary>
+ private static StreamingContext GetStreamingContext(IBinaryReader reader)
+ {
+ return new StreamingContext(StreamingContextStates.All, reader);
+ }
+
+ /// <summary>
+ /// Gets the streaming context.
+ /// </summary>
+ private static StreamingContext GetStreamingContext(IBinaryWriter writer)
+ {
+ return new StreamingContext(StreamingContextStates.All, writer);
+ }
}
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySurrogateTypeDescriptor.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySurrogateTypeDescriptor.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySurrogateTypeDescriptor.cs
index adba577..8c7e5e9 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySurrogateTypeDescriptor.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySurrogateTypeDescriptor.cs
@@ -19,6 +19,7 @@ namespace Apache.Ignite.Core.Impl.Binary
{
using System;
using System.Collections.Generic;
+ using System.Diagnostics;
using Apache.Ignite.Core.Binary;
using Apache.Ignite.Core.Impl.Binary.Structure;
@@ -51,10 +52,14 @@ namespace Apache.Ignite.Core.Impl.Binary
/// </summary>
/// <param name="cfg">Configuration.</param>
/// <param name="id">Type ID.</param>
- public BinarySurrogateTypeDescriptor(BinaryConfiguration cfg, int id)
+ /// <param name="typeName">Name of the type.</param>
+ public BinarySurrogateTypeDescriptor(BinaryConfiguration cfg, int id, string typeName)
{
+ Debug.Assert(cfg != null);
+
_cfg = cfg;
_id = id;
+ _name = typeName;
}
/// <summary>
@@ -170,5 +175,11 @@ namespace Apache.Ignite.Core.Impl.Binary
{
get { return _schema; }
}
+
+ /** <inheritDoc /> */
+ public bool IsRegistered
+ {
+ get { return false; }
+ }
}
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySystemHandlers.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySystemHandlers.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySystemHandlers.cs
index beb2668..60bbb46 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySystemHandlers.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySystemHandlers.cs
@@ -22,7 +22,6 @@ namespace Apache.Ignite.Core.Impl.Binary
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
- using Apache.Ignite.Core.Binary;
using Apache.Ignite.Core.Impl.Binary.IO;
using Apache.Ignite.Core.Impl.Common;
@@ -169,8 +168,7 @@ namespace Apache.Ignite.Core.Impl.Binary
var handler = FindWriteHandler(t, out supportsHandles);
- return handler == null ? null : new BinarySystemWriteHandler(handler, supportsHandles,
- handler == WriteSerializable);
+ return handler == null ? null : new BinarySystemWriteHandler(handler, supportsHandles);
});
}
@@ -191,8 +189,6 @@ namespace Apache.Ignite.Core.Impl.Binary
return WriteString;
if (type == typeof(decimal))
return WriteDecimal;
- if (type == typeof(DateTime))
- return WriteDate;
if (type == typeof(Guid))
return WriteGuid;
if (type == typeof (BinaryObject))
@@ -251,16 +247,11 @@ namespace Apache.Ignite.Core.Impl.Binary
// Enums.
if (elemType.IsEnum || elemType == typeof(BinaryEnum))
return WriteEnumArray;
-
+
// Object array.
- if (elemType == typeof (object) || elemType == typeof (IBinaryObject) ||
- elemType == typeof (BinaryObject))
- return WriteArray;
+ return WriteArray;
}
- if (type.IsSerializable)
- return WriteSerializable;
-
return null;
}
@@ -315,16 +306,6 @@ namespace Apache.Ignite.Core.Impl.Binary
}
/// <summary>
- /// Write date.
- /// </summary>
- /// <param name="ctx">Context.</param>
- /// <param name="obj">Value.</param>
- private static void WriteDate(BinaryWriter ctx, object obj)
- {
- ctx.Write(new DateTimeHolder((DateTime) obj));
- }
-
- /// <summary>
/// Write string.
/// </summary>
/// <param name="ctx">Context.</param>
@@ -535,21 +516,17 @@ namespace Apache.Ignite.Core.Impl.Binary
{
ctx.Stream.WriteByte(BinaryUtils.TypeArrayEnum);
- var desc = ctx.Marshaller.GetDescriptor(obj.GetType());
-
- int typeId = desc == null ? BinaryUtils.ObjTypeId : desc.TypeId;
-
- BinaryUtils.WriteArray((Array)obj, ctx, typeId);
+ BinaryUtils.WriteArray((Array) obj, ctx);
}
- /**
- * <summary>Write array.</summary>
- */
+ /// <summary>
+ /// Writes the array.
+ /// </summary>
private static void WriteArray(BinaryWriter ctx, object obj)
{
ctx.Stream.WriteByte(BinaryUtils.TypeArray);
- BinaryUtils.WriteArray((Array)obj, ctx);
+ BinaryUtils.WriteArray((Array) obj, ctx);
}
/**
@@ -603,16 +580,6 @@ namespace Apache.Ignite.Core.Impl.Binary
ctx.WriteInt(binEnum.EnumValue);
}
- /// <summary>
- /// Writes serializable.
- /// </summary>
- /// <param name="writer">The writer.</param>
- /// <param name="o">The object.</param>
- private static void WriteSerializable(BinaryWriter writer, object o)
- {
- writer.Write(new SerializableObjectHolder(o));
- }
-
/**
* <summary>Read enum array.</summary>
*/
@@ -623,13 +590,36 @@ namespace Apache.Ignite.Core.Impl.Binary
return BinaryUtils.ReadTypedArray(ctx, true, elemType);
}
- /**
- * <summary>Read array.</summary>
- */
+ /// <summary>
+ /// Reads the array.
+ /// </summary>
private static object ReadArray(BinaryReader ctx, Type type)
{
- var elemType = type.GetElementType() ?? typeof(object);
+ var elemType = type.GetElementType();
+
+ if (elemType == null)
+ {
+ if (ctx.Mode == BinaryMode.ForceBinary)
+ {
+ // Forced binary mode: use object because primitives are not represented as IBinaryObject.
+ elemType = typeof(object);
+ }
+ else
+ {
+ // Infer element type from typeId.
+ var typeId = ctx.ReadInt();
+
+ if (typeId != BinaryUtils.ObjTypeId)
+ {
+ elemType = ctx.Marshaller.GetDescriptor(true, typeId, true).Type;
+ }
+
+ return BinaryUtils.ReadTypedArray(ctx, false, elemType ?? typeof(object));
+ }
+ }
+ // Element type is known, no need to check typeId.
+ // In case of incompatible types we'll get exception either way.
return BinaryUtils.ReadTypedArray(ctx, true, elemType);
}
@@ -798,23 +788,17 @@ namespace Apache.Ignite.Core.Impl.Binary
/** */
private readonly bool _supportsHandles;
- /** */
- private readonly bool _isSerializable;
-
/// <summary>
/// Initializes a new instance of the <see cref="BinarySystemWriteHandler" /> class.
/// </summary>
/// <param name="writeAction">The write action.</param>
/// <param name="supportsHandles">Handles flag.</param>
- /// <param name="isSerializable">Determines whether this handler writes objects as serializable.</param>
- public BinarySystemWriteHandler(Action<BinaryWriter, object> writeAction, bool supportsHandles,
- bool isSerializable)
+ public BinarySystemWriteHandler(Action<BinaryWriter, object> writeAction, bool supportsHandles)
{
Debug.Assert(writeAction != null);
_writeAction = writeAction;
_supportsHandles = supportsHandles;
- _isSerializable = isSerializable;
}
/// <summary>
@@ -834,13 +818,5 @@ namespace Apache.Ignite.Core.Impl.Binary
{
get { return _supportsHandles; }
}
-
- /// <summary>
- /// Gets or sets a value indicating whether this handler writes objects as serializable
- /// </summary>
- public bool IsSerializable
- {
- get { return _isSerializable; }
- }
}
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySystemTypeSerializer.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySystemTypeSerializer.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySystemTypeSerializer.cs
index b416848..1ea1f0b 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySystemTypeSerializer.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySystemTypeSerializer.cs
@@ -48,7 +48,7 @@ namespace Apache.Ignite.Core.Impl.Binary
}
/** <inheritDoc /> */
- public T1 ReadBinary<T1>(BinaryReader reader, Type type, int pos)
+ public T1 ReadBinary<T1>(BinaryReader reader, IBinaryTypeDescriptor desc, int pos)
{
return TypeCaster<T1>.Cast(_ctor(reader));
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryUtils.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryUtils.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryUtils.cs
index 2050f67..bb58ea5 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryUtils.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryUtils.cs
@@ -52,6 +52,9 @@ namespace Apache.Ignite.Core.Impl.Binary
/** Type: object. */
public const byte TypeObject = HdrFull;
+ /** Type: unregistered. */
+ public const byte TypeUnregistered = 0;
+
/** Type: unsigned byte. */
public const byte TypeByte = 1;
@@ -166,12 +169,6 @@ namespace Apache.Ignite.Core.Impl.Binary
/** Type: Compute job wrapper. */
public const byte TypeComputeJobWrapper = 86;
- /** Type: Serializable wrapper. */
- public const byte TypeSerializableHolder = 87;
-
- /** Type: DateTime wrapper. */
- public const byte TypeDateTimeHolder = 93;
-
/** Type: action wrapper. */
public const byte TypeComputeActionJob = 88;
@@ -235,8 +232,12 @@ namespace Apache.Ignite.Core.Impl.Binary
/** Bindig flags for static search. */
private const BindingFlags BindFlagsStatic = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
- /** Default poratble marshaller. */
- private static readonly Marshaller Marsh = new Marshaller(null);
+ /** System marshaller. */
+ private static readonly Marshaller Marsh = new Marshaller(
+ new BinaryConfiguration {CompactFooter = false})
+ {
+ RegistrationDisabled = true
+ };
/** Method: ReadArray. */
public static readonly MethodInfo MtdhReadArray =
@@ -1265,14 +1266,31 @@ namespace Apache.Ignite.Core.Impl.Binary
/// </summary>
/// <param name="val">Array.</param>
/// <param name="ctx">Write context.</param>
- /// <param name="elementType">Type of the array element.</param>
- public static void WriteArray(Array val, BinaryWriter ctx, int elementType = ObjTypeId)
+ /// <param name="elemTypeId">The element type id.</param>
+ public static void WriteArray(Array val, BinaryWriter ctx, int? elemTypeId = null)
{
Debug.Assert(val != null && ctx != null);
IBinaryStream stream = ctx.Stream;
- stream.WriteInt(elementType);
+ if (elemTypeId != null && elemTypeId != TypeUnregistered)
+ {
+ stream.WriteInt(elemTypeId.Value);
+ }
+ else
+ {
+ var elemType = val.GetType().GetElementType();
+
+ var typeId = ObjTypeId;
+
+ if (elemType != typeof(object))
+ typeId = ctx.Marshaller.GetDescriptor(elemType).TypeId;
+
+ stream.WriteInt(typeId);
+
+ if (typeId == TypeUnregistered)
+ ctx.WriteString(elemType.FullName);
+ }
stream.WriteInt(val.Length);
@@ -1313,7 +1331,12 @@ namespace Apache.Ignite.Core.Impl.Binary
var pos = stream.Position;
if (typed)
- stream.ReadInt();
+ {
+ int typeId = stream.ReadInt();
+
+ if (typeId == TypeUnregistered)
+ ctx.ReadString();
+ }
int len = stream.ReadInt();
@@ -1538,7 +1561,7 @@ namespace Apache.Ignite.Core.Impl.Binary
{
var desc = marshaller.GetDescriptor(enumType);
- return desc == null ? ObjTypeId : desc.TypeId;
+ return desc.TypeId;
}
throw new BinaryObjectException("Only Int32 underlying type is supported for enums: " +
@@ -1559,10 +1582,10 @@ namespace Apache.Ignite.Core.Impl.Binary
return TypeCaster<T>.Cast(value);
// All enums are user types
- var desc = marsh.GetDescriptor(true, typeId);
+ var desc = marsh.GetDescriptor(true, typeId, true);
if (desc == null || desc.Type == null)
- throw new BinaryObjectException("Unknown enum type id: " + typeId);
+ return TypeCaster<T>.Cast(value);
return (T)Enum.ToObject(desc.Type, value);
}
@@ -1743,7 +1766,6 @@ namespace Apache.Ignite.Core.Impl.Binary
public static int FieldId(int typeId, string fieldName, IBinaryNameMapper nameMapper,
IBinaryIdMapper idMapper)
{
- Debug.Assert(typeId != 0);
Debug.Assert(fieldName != null);
fieldName = ConvertFieldName(fieldName, nameMapper);
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/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 0490ec8..1388d16 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryWriter.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryWriter.cs
@@ -48,27 +48,12 @@ namespace Apache.Ignite.Core.Impl.Binary
/** Metadatas collected during this write session. */
private IDictionary<int, BinaryType> _metas;
- /** Current type ID. */
- private int _curTypeId;
-
- /** Current name converter */
- private IBinaryNameMapper _curConverter;
-
- /** Current mapper. */
- private IBinaryIdMapper _curMapper;
-
- /** Current object start position. */
- private int _curPos;
-
- /** Current raw position. */
- private int _curRawPos;
+ /** Current stack frame. */
+ private Frame _frame;
/** Whether we are currently detaching an object. */
private bool _detaching;
- /** Current type structure tracker, */
- private BinaryStructureTracker _curStruct;
-
/** Schema holder. */
private readonly BinaryObjectSchemaHolder _schema = BinaryObjectSchemaHolder.Current;
@@ -150,7 +135,7 @@ namespace Apache.Ignite.Core.Impl.Binary
/// <param name="val">Byte value.</param>
public void WriteByte(string fieldName, byte val)
{
- WriteFieldId(fieldName, BinaryUtils.TypeBool);
+ WriteFieldId(fieldName, BinaryUtils.TypeByte);
WriteByteField(val);
}
@@ -875,23 +860,13 @@ namespace Apache.Ignite.Core.Impl.Binary
{
var desc = _marsh.GetDescriptor(val.GetType());
- if (desc != null)
- {
- var metaHnd = _marsh.GetBinaryTypeHandler(desc);
+ var metaHnd = _marsh.GetBinaryTypeHandler(desc);
- _stream.WriteByte(BinaryUtils.TypeEnum);
+ _stream.WriteByte(BinaryUtils.TypeEnum);
- BinaryUtils.WriteEnum(this, val);
+ BinaryUtils.WriteEnum(this, val);
- SaveMetadata(desc, metaHnd.OnObjectWriteFinished());
- }
- else
- {
- // Unregistered enum, write with object type id.
- _stream.WriteByte(BinaryUtils.TypeEnum);
- _stream.WriteInt(BinaryUtils.ObjTypeId);
- _stream.WriteInt(TypeCaster<int>.Cast(val));
- }
+ SaveMetadata(desc, metaHnd.OnObjectWriteFinished());
}
}
@@ -931,9 +906,7 @@ namespace Apache.Ignite.Core.Impl.Binary
{
_stream.WriteByte(BinaryUtils.TypeArrayEnum);
- var elTypeId = elementTypeId ?? BinaryUtils.GetEnumTypeId(val.GetType().GetElementType(), Marshaller);
-
- BinaryUtils.WriteArray(val, this, elTypeId);
+ BinaryUtils.WriteArray(val, this, elementTypeId);
}
}
@@ -1089,8 +1062,8 @@ namespace Apache.Ignite.Core.Impl.Binary
/// </returns>
public IBinaryRawWriter GetRawWriter()
{
- if (_curRawPos == 0)
- _curRawPos = _stream.Position;
+ if (_frame.RawPos == 0)
+ _frame.RawPos = _stream.Position;
return this;
}
@@ -1159,121 +1132,122 @@ namespace Apache.Ignite.Core.Impl.Binary
if (WriteBuilderSpecials(obj))
return;
- // Suppose that we faced normal object and perform descriptor lookup.
- IBinaryTypeDescriptor desc = _marsh.GetDescriptor(type);
+ // Are we dealing with a well-known type?
+ var handler = BinarySystemHandlers.GetWriteHandler(type);
- if (desc != null)
+ if (handler != null)
{
- // Writing normal object.
- var pos = _stream.Position;
-
- // Dealing with handles.
- if (desc.Serializer.SupportsHandles && WriteHandle(pos, obj))
+ if (handler.SupportsHandles && WriteHandle(_stream.Position, obj))
return;
- // Skip header length as not everything is known now
- _stream.Seek(BinaryObjectHeader.Size, SeekOrigin.Current);
-
- // Preserve old frame.
- int oldTypeId = _curTypeId;
- IBinaryNameMapper oldConverter = _curConverter;
- IBinaryIdMapper oldMapper = _curMapper;
- int oldRawPos = _curRawPos;
- var oldPos = _curPos;
-
- var oldStruct = _curStruct;
+ handler.Write(this, obj);
- // Push new frame.
- _curTypeId = desc.TypeId;
- _curConverter = desc.NameMapper;
- _curMapper = desc.IdMapper;
- _curRawPos = 0;
- _curPos = pos;
+ return;
+ }
- _curStruct = new BinaryStructureTracker(desc, desc.WriterTypeStructure);
- var schemaIdx = _schema.PushSchema();
+ // Suppose that we faced normal object and perform descriptor lookup.
+ var desc = _marsh.GetDescriptor(type);
- try
- {
- // Write object fields.
- desc.Serializer.WriteBinary(obj, this);
- var dataEnd = _stream.Position;
+ // Writing normal object.
+ var pos = _stream.Position;
- // Write schema
- var schemaOffset = dataEnd - pos;
+ // Dealing with handles.
+ if (desc.Serializer.SupportsHandles && WriteHandle(pos, obj))
+ return;
- int schemaId;
-
- var flags = desc.UserType
- ? BinaryObjectHeader.Flag.UserType
- : BinaryObjectHeader.Flag.None;
+ // Skip header length as not everything is known now
+ _stream.Seek(BinaryObjectHeader.Size, SeekOrigin.Current);
- if (Marshaller.CompactFooter && desc.UserType)
- flags |= BinaryObjectHeader.Flag.CompactFooter;
+ // Write type name for unregistered types
+ if (!desc.IsRegistered)
+ WriteString(type.AssemblyQualifiedName);
- var hasSchema = _schema.WriteSchema(_stream, schemaIdx, out schemaId, ref flags);
+ var headerSize = _stream.Position - pos;
- if (hasSchema)
- {
- flags |= BinaryObjectHeader.Flag.HasSchema;
+ // Preserve old frame.
+ var oldFrame = _frame;
- // Calculate and write header.
- if (_curRawPos > 0)
- _stream.WriteInt(_curRawPos - pos); // raw offset is in the last 4 bytes
+ // Push new frame.
+ _frame.RawPos = 0;
+ _frame.Pos = pos;
+ _frame.Struct = new BinaryStructureTracker(desc, desc.WriterTypeStructure);
+ _frame.HasCustomTypeData = false;
- // Update schema in type descriptor
- if (desc.Schema.Get(schemaId) == null)
- desc.Schema.Add(schemaId, _schema.GetSchema(schemaIdx));
- }
- else
- schemaOffset = BinaryObjectHeader.Size;
+ var schemaIdx = _schema.PushSchema();
- if (_curRawPos > 0)
- flags |= BinaryObjectHeader.Flag.HasRaw;
+ try
+ {
+ // Write object fields.
+ desc.Serializer.WriteBinary(obj, this);
+ var dataEnd = _stream.Position;
- var len = _stream.Position - pos;
+ // Write schema
+ var schemaOffset = dataEnd - pos;
- var comparer = BinaryUtils.GetEqualityComparer(desc);
+ int schemaId;
+
+ var flags = desc.UserType
+ ? BinaryObjectHeader.Flag.UserType
+ : BinaryObjectHeader.Flag.None;
- var hashCode = comparer.GetHashCode(Stream, pos + BinaryObjectHeader.Size,
- dataEnd - pos - BinaryObjectHeader.Size, _schema, schemaIdx, _marsh, desc);
+ if (_frame.HasCustomTypeData)
+ flags |= BinaryObjectHeader.Flag.CustomDotNetType;
- var header = new BinaryObjectHeader(desc.TypeId, hashCode, len, schemaId, schemaOffset, flags);
+ if (Marshaller.CompactFooter && desc.UserType)
+ flags |= BinaryObjectHeader.Flag.CompactFooter;
- BinaryObjectHeader.Write(header, _stream, pos);
+ var hasSchema = _schema.WriteSchema(_stream, schemaIdx, out schemaId, ref flags);
- Stream.Seek(pos + len, SeekOrigin.Begin); // Seek to the end
- }
- finally
+ if (hasSchema)
{
- _schema.PopSchema(schemaIdx);
+ flags |= BinaryObjectHeader.Flag.HasSchema;
+
+ // Calculate and write header.
+ if (_frame.RawPos > 0)
+ _stream.WriteInt(_frame.RawPos - pos); // raw offset is in the last 4 bytes
+
+ // Update schema in type descriptor
+ if (desc.Schema.Get(schemaId) == null)
+ desc.Schema.Add(schemaId, _schema.GetSchema(schemaIdx));
}
+ else
+ schemaOffset = headerSize;
+
+ if (_frame.RawPos > 0)
+ flags |= BinaryObjectHeader.Flag.HasRaw;
+
+ var len = _stream.Position - pos;
+
+ var comparer = BinaryUtils.GetEqualityComparer(desc);
+
+ var hashCode = comparer.GetHashCode(Stream, pos + BinaryObjectHeader.Size,
+ dataEnd - pos - BinaryObjectHeader.Size, _schema, schemaIdx, _marsh, desc);
- // Apply structure updates if any.
- _curStruct.UpdateWriterStructure(this);
+ var header = new BinaryObjectHeader(desc.IsRegistered ? desc.TypeId : BinaryUtils.TypeUnregistered,
+ hashCode, len, schemaId, schemaOffset, flags);
- // Restore old frame.
- _curTypeId = oldTypeId;
- _curConverter = oldConverter;
- _curMapper = oldMapper;
- _curRawPos = oldRawPos;
- _curPos = oldPos;
+ BinaryObjectHeader.Write(header, _stream, pos);
- _curStruct = oldStruct;
+ Stream.Seek(pos + len, SeekOrigin.Begin); // Seek to the end
}
- else
+ finally
{
- // Are we dealing with a well-known type?
- var handler = BinarySystemHandlers.GetWriteHandler(type);
+ _schema.PopSchema(schemaIdx);
+ }
- if (handler == null) // We did our best, object cannot be marshalled.
- throw BinaryUtils.GetUnsupportedTypeException(type, obj);
-
- if (handler.SupportsHandles && WriteHandle(_stream.Position, obj))
- return;
+ // Apply structure updates if any.
+ _frame.Struct.UpdateWriterStructure(this);
- handler.Write(this, obj);
- }
+ // Restore old frame.
+ _frame = oldFrame;
+ }
+
+ /// <summary>
+ /// Marks current object with a custom type data flag.
+ /// </summary>
+ public void SetCustomTypeDataFlag(bool hasCustomTypeData)
+ {
+ _frame.HasCustomTypeData = hasCustomTypeData;
}
/// <summary>
@@ -1455,12 +1429,12 @@ namespace Apache.Ignite.Core.Impl.Binary
/// <param name="fieldTypeId">Field type ID.</param>
private void WriteFieldId(string fieldName, byte fieldTypeId)
{
- if (_curRawPos != 0)
+ if (_frame.RawPos != 0)
throw new BinaryObjectException("Cannot write named fields after raw data is written.");
- var fieldId = _curStruct.GetFieldId(fieldName, fieldTypeId);
+ var fieldId = _frame.Struct.GetFieldId(fieldName, fieldTypeId);
- _schema.PushField(fieldId, _stream.Position - _curPos);
+ _schema.PushField(fieldId, _stream.Position - _frame.Pos);
}
/// <summary>
@@ -1489,5 +1463,23 @@ namespace Apache.Ignite.Core.Impl.Binary
_metas[desc.TypeId] = new BinaryType(desc, fields);
}
}
+
+ /// <summary>
+ /// Stores current writer stack frame.
+ /// </summary>
+ private struct Frame
+ {
+ /** Current object start position. */
+ public int Pos;
+
+ /** Current raw position. */
+ public int RawPos;
+
+ /** Current type structure tracker. */
+ public BinaryStructureTracker Struct;
+
+ /** Custom type data. */
+ public bool HasCustomTypeData;
+ }
}
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/DateTimeHolder.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/DateTimeHolder.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/DateTimeHolder.cs
deleted file mode 100644
index 21c56a9..0000000
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/DateTimeHolder.cs
+++ /dev/null
@@ -1,101 +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.Diagnostics;
- using Apache.Ignite.Core.Binary;
-
- /// <summary>
- /// Wraps DateTime item in a binarizable.
- /// </summary>
- internal struct DateTimeHolder : IBinaryWriteAware
- {
- /** */
- private readonly DateTime _item;
-
- /// <summary>
- /// Constructor.
- /// </summary>
- /// <param name="item">The item to wrap.</param>
- public DateTimeHolder(DateTime item)
- {
- _item = item;
- }
-
- /// <summary>
- /// Constructor.
- /// </summary>
- /// <param name="reader">The reader.</param>
- public DateTimeHolder(IBinaryRawReader reader)
- {
- Debug.Assert(reader != null);
-
- _item = DateTime.FromBinary(reader.ReadLong());
- }
-
- /// <summary>
- /// Gets the item to wrap.
- /// </summary>
- public DateTime Item
- {
- get { return _item; }
- }
-
- /** <inheritDoc /> */
- public void WriteBinary(IBinaryWriter writer)
- {
- Debug.Assert(writer != null);
-
- writer.GetRawWriter().WriteLong(_item.ToBinary());
- }
-
- /** <inheritDoc /> */
- public override bool Equals(object obj)
- {
- if (ReferenceEquals(null, obj)) return false;
- return obj is DateTimeHolder && Equals((DateTimeHolder) obj);
- }
-
- /** <inheritDoc /> */
- public override int GetHashCode()
- {
- return _item.GetHashCode();
- }
-
- /** <inheritDoc /> */
- public static bool operator ==(DateTimeHolder left, DateTimeHolder right)
- {
- return left.Equals(right);
- }
-
- /** <inheritDoc /> */
- public static bool operator !=(DateTimeHolder left, DateTimeHolder right)
- {
- return !left.Equals(right);
- }
-
- /// <summary>
- /// Checks equality.
- /// </summary>
- private bool Equals(DateTimeHolder other)
- {
- return _item.Equals(other._item);
- }
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/DateTimeSerializer.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/DateTimeSerializer.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/DateTimeSerializer.cs
deleted file mode 100644
index bea7d58..0000000
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/DateTimeSerializer.cs
+++ /dev/null
@@ -1,48 +0,0 @@
-\ufeff/*
- * 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 Apache.Ignite.Core.Impl.Common;
-
- /// <summary>
- /// DateTime serializer.
- /// </summary>
- internal class DateTimeSerializer : IBinarySerializerInternal
- {
- /** <inheritdoc /> */
- public void WriteBinary<T>(T obj, BinaryWriter writer)
- {
- TypeCaster<DateTimeHolder>.Cast(obj).WriteBinary(writer);
- }
-
- /** <inheritdoc /> */
- public T ReadBinary<T>(BinaryReader reader, Type type, int pos)
- {
- var holder = new DateTimeHolder(reader);
-
- return TypeCaster<T>.Cast(holder.Item);
- }
-
- /** <inheritdoc /> */
- public bool SupportsHandles
- {
- get { return false; }
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/DeserializationCallbackProcessor.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/DeserializationCallbackProcessor.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/DeserializationCallbackProcessor.cs
new file mode 100644
index 0000000..3b21946
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/DeserializationCallbackProcessor.cs
@@ -0,0 +1,102 @@
+\ufeff/*
+ * 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.Collections.Generic;
+ using System.Runtime.Serialization;
+ using System.Threading;
+
+ /// <summary>
+ /// Tracks object graph and invokes <see cref="IDeserializationCallback" />.
+ /// <para />
+ /// <see cref="IDeserializationCallback.OnDeserialization" /> must be called after entire object graph has been
+ /// deserialized. We preserve all objects in a thread-local list and invoke callbacks once all objects
+ /// are fully deserialized.
+ /// </summary>
+ internal static class DeserializationCallbackProcessor
+ {
+ /// <summary>
+ /// Object graph for current thread.
+ /// </summary>
+ private static readonly ThreadLocal<ObjectGraph> Graph
+ = new ThreadLocal<ObjectGraph>(() => new ObjectGraph());
+
+ /// <summary>
+ /// Register an object for deserialization callback.
+ /// </summary>
+ /// <param name="obj">The object.</param>
+ /// <returns>Id of the object.</returns>
+ public static void Push(object obj)
+ {
+ var graph = Graph.Value;
+
+ graph.Depth++;
+
+ var cb = obj as IDeserializationCallback;
+
+ if (cb != null)
+ {
+ graph.Objects.Add(cb);
+ }
+ }
+
+ /// <summary>
+ /// Called when deserialization of an object has completed.
+ /// When Pop() has been called for all registered objects, all callbacks are invoked.
+ /// </summary>
+ public static void Pop()
+ {
+ var graph = Graph.Value;
+
+ graph.Depth--;
+
+ if (graph.Depth == 0)
+ {
+ // Entire graph has been deserialized: invoke callbacks in direct order (like BinaryFormatter does).
+ foreach (var obj in graph.Objects)
+ {
+ obj.OnDeserialization(null);
+ }
+
+ graph.Objects.Clear();
+ }
+ }
+
+ /// <summary>
+ /// Object graph.
+ /// </summary>
+ private class ObjectGraph
+ {
+ /** */
+ private readonly List<IDeserializationCallback> _objects = new List<IDeserializationCallback>();
+
+ /// <summary>
+ /// Gets or sets the depth.
+ /// </summary>
+ public int Depth { get; set; }
+
+ /// <summary>
+ /// Gets the objects.
+ /// </summary>
+ public List<IDeserializationCallback> Objects
+ {
+ get { return _objects; }
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/IBinarySerializerInternal.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/IBinarySerializerInternal.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/IBinarySerializerInternal.cs
index 58844d6..b775999 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/IBinarySerializerInternal.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/IBinarySerializerInternal.cs
@@ -17,8 +17,6 @@
namespace Apache.Ignite.Core.Impl.Binary
{
- using System;
-
/// <summary>
/// Internal generic serializer interface.
/// </summary>
@@ -32,7 +30,7 @@ namespace Apache.Ignite.Core.Impl.Binary
/// <summary>
/// Read binary object.
/// </summary>
- T ReadBinary<T>(BinaryReader reader, Type type, int pos);
+ T ReadBinary<T>(BinaryReader reader, IBinaryTypeDescriptor desc, int pos);
/// <summary>
/// Gets a value indicating whether this serializer supports handles.
http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/IBinaryTypeDescriptor.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/IBinaryTypeDescriptor.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/IBinaryTypeDescriptor.cs
index 6c7e360..6bec70f 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/IBinaryTypeDescriptor.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/IBinaryTypeDescriptor.cs
@@ -112,5 +112,13 @@ namespace Apache.Ignite.Core.Impl.Binary
/// Gets the schema.
/// </summary>
BinaryObjectSchema Schema { get; }
+
+ /// <summary>
+ /// Gets a value indicating whether this descriptor is registered in the cluster.
+ /// </summary>
+ /// <value>
+ /// <c>true</c> if this instance is registered; otherwise, <c>false</c>.
+ /// </value>
+ bool IsRegistered { get; }
}
}