You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by ag...@apache.org on 2017/03/31 16:22:45 UTC
[11/18] ignite git commit: IGNITE-2703 .NET: Dynamic type registration
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>