コード例 #1
0
        /// <summary>
        /// Does not support deserializing of anonymous types
        /// Type should be covered by preceeding resolvers in complex/standard resolver
        /// </summary>
        private object DeserializeByTypeName(string typeName, byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize)
        {
            // try get type with assembly name, throw if not found
            var type = Type.GetType(typeName, true);
            var ti   = type.GetTypeInfo();

            KeyValuePair <object, DeserializeMethod> formatterAndDelegate;

            if (type == typeof(object))
            {
                formatterAndDelegate = new KeyValuePair <object, DeserializeMethod>(null, (object p1, byte[] p2, int p3, IFormatterResolver p4, out int p5) =>
                {
                    p5 = 0;
                    return(new object());
                });
            }
            else
            {
                lock (deserializers)
                {
                    if (!deserializers.TryGetValue(type, out formatterAndDelegate))
                    {
                        var formatter = formatterResolver.GetFormatterDynamic(type);
                        if (formatter == null)
                        {
                            throw new FormatterNotRegisteredException(type.FullName + " is not registered in this resolver. resolver:" + formatterResolver.GetType().Name);
                        }

                        var formatterType = typeof(IMessagePackFormatter <>).MakeGenericType(type);
                        var param0        = Expression.Parameter(typeof(object), "formatter");
                        var param1        = Expression.Parameter(typeof(byte[]), "bytes");
                        var param2        = Expression.Parameter(typeof(int), "offset");
                        var param3        = Expression.Parameter(typeof(IFormatterResolver), "formatterResolver");
                        var param4        = Expression.Parameter(typeof(int).MakeByRefType(), "readSize");

                        var deserializeMethodInfo = formatterType.GetRuntimeMethod("Deserialize", new[] { typeof(byte[]), typeof(int), typeof(IFormatterResolver), typeof(int).MakeByRefType() });

                        var deserialize = Expression.Call(
                            Expression.Convert(param0, formatterType),
                            deserializeMethodInfo,
                            param1,
                            param2,
                            param3,
                            param4);

                        Expression body = deserialize;
                        if (ti.IsValueType)
                        {
                            body = Expression.Convert(deserialize, typeof(object));
                        }
                        var lambda = Expression.Lambda <DeserializeMethod>(body, param0, param1, param2, param3, param4).Compile();

                        formatterAndDelegate = new KeyValuePair <object, DeserializeMethod>(formatter, lambda);

                        deserializers[type] = formatterAndDelegate;
                    }
                }
            }
            return(formatterAndDelegate.Value(formatterAndDelegate.Key, bytes, offset, formatterResolver, out readSize));
        }
コード例 #2
0
        protected U DeSerializeProperty <U>(Func <object> valueFormatterHandler, byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize)
        {
            var initialSize = offset;

            if (bytes[offset] == 0xc0)
            {
                readSize = 1;
                return(default(U));
            }

            //int fieldNameSize = 0;
            //_ = MessagePackBinary.ReadString(bytes, offset, out fieldNameSize);
            //offset += fieldNameSize;
            var fromResolver = formatterResolver.GetFormatterDynamic(typeof(U));
            var fromHandler  = valueFormatterHandler != null?valueFormatterHandler() : fromResolver;

            var primaryElementFormatter = fromResolver != null ? fromResolver : fromHandler;

            int    valueSize = 0;
            object instance  = DeSerializeField(typeof(U), bytes, offset, primaryElementFormatter, formatterResolver, out valueSize);

            offset  += valueSize;
            readSize = offset - initialSize;
            return((U)instance);
        }
コード例 #3
0
        public int Serialize(ref byte[] bytes, int offset, object value, IFormatterResolver formatterResolver)
        {
            if (value == null)
            {
                return(MessagePackBinary.WriteNil(ref bytes, offset));
            }

            var type = value.GetType();
            var ti   = type.GetTypeInfo();

            if (type == typeof(object))
            {
                // serialize to empty map
                return(MessagePackBinary.WriteMapHeader(ref bytes, offset, 0));
            }

            KeyValuePair <object, SerializeMethod> formatterAndDelegate;

            lock (serializers)
            {
                if (!serializers.TryGetValue(type, out formatterAndDelegate))
                {
                    var formatter = formatterResolver.GetFormatterDynamic(type);
                    if (formatter == null)
                    {
                        throw new FormatterNotRegisteredException(type.FullName + " is not registered in this resolver. resolver:" + formatterResolver.GetType().Name);
                    }

                    serializers.TryAdd(type, t =>
                    {
                        var formatterType = typeof(IMessagePackFormatter <>).MakeGenericType(t);
                        var param0        = Expression.Parameter(typeof(object), "formatter");
                        var param1        = Expression.Parameter(typeof(byte[]).MakeByRefType(), "bytes");
                        var param2        = Expression.Parameter(typeof(int), "offset");
                        var param3        = Expression.Parameter(typeof(object), "value");
                        var param4        = Expression.Parameter(typeof(IFormatterResolver), "formatterResolver");

                        var serializeMethodInfo = formatterType.GetRuntimeMethod("Serialize", new[] { typeof(byte[]).MakeByRefType(), typeof(int), t, typeof(IFormatterResolver) });

                        var body = Expression.Call(
                            Expression.Convert(param0, formatterType),
                            serializeMethodInfo,
                            param1,
                            param2,
                            ti.IsValueType ? Expression.Unbox(param3, t) : Expression.Convert(param3, t),
                            param4);

                        var lambda = Expression.Lambda <SerializeMethod>(body, param0, param1, param2, param3, param4).Compile();

                        formatterAndDelegate = new KeyValuePair <object, SerializeMethod>(formatter, lambda);

                        return(formatterAndDelegate);
                    });
                }
            }

            return(formatterAndDelegate.Value(formatterAndDelegate.Key, ref bytes, offset, value, formatterResolver));
        }
コード例 #4
0
        /// <summary>
        /// Check whether type is readable.
        /// </summary>
        /// <param name="type">Type to check.</param>
        /// <returns></returns>
        /// <exception cref="T:System.ArgumentNullException"><paramref name="type"/> is <see langword="null"/></exception>
        public bool CanRead(Type type)
        {
            if (type == null)
            {
                throw new ArgumentNullException(nameof(type));
            }
            if (!_readableTypes.TryGetValue(type, out bool canRead))
            {
                canRead        = _formatterResolver.GetFormatterDynamic(type) != null;
                _readableTypes = _readableTypes.Add(type, canRead);

                return(canRead);
            }

            return(canRead);
        }
コード例 #5
0
        private static void GetFormatterAndDelegateSlow(Type type, IFormatterResolver formatterResolver, out KeyValuePair <object, DeserializeMethod> formatterAndDelegate)
        {
            lock (s_deserializers)
            {
                if (!s_deserializers.TryGetValue(type, out formatterAndDelegate))
                {
                    var formatter = formatterResolver.GetFormatterDynamic(type);
                    if (formatter == null)
                    {
                        ThrowHelper.ThrowFormatterNotRegisteredException(type, formatterResolver);
                    }

                    var formatterType = typeof(IMessagePackFormatter <>).GetCachedGenericType(type);
                    var param0        = Expression.Parameter(typeof(object), "formatter");
                    var param1        = Expression.Parameter(typeof(MessagePackReader).MakeByRefType(), "reader");
                    var param2        = Expression.Parameter(typeof(IFormatterResolver), "formatterResolver");

                    var deserializeMethodInfo = formatterType.GetRuntimeMethod("Deserialize", new[] { typeof(MessagePackReader).MakeByRefType(), typeof(IFormatterResolver) });

                    var deserialize = Expression.Call(
                        Expression.Convert(param0, formatterType),
                        deserializeMethodInfo,
                        param1,
                        param2);

                    Expression body = deserialize;
                    if (type.IsValueType)
                    {
                        body = Expression.Convert(deserialize, typeof(object));
                    }
                    var lambda = Expression.Lambda <DeserializeMethod>(body, param0, param1, param2).Compile();

                    formatterAndDelegate = new KeyValuePair <object, DeserializeMethod>(formatter, lambda);
                    s_deserializers.TryAdd(type, formatterAndDelegate);
                }
            }
        }
コード例 #6
0
        private static void GetFormatterAndDelegateSlow(Type expectedType, IFormatterResolver formatterResolver, out KeyValuePair <object, SerializeMethod> formatterAndDelegate)
        {
            lock (s_serializers) // double check locking...
            {
                if (!s_serializers.TryGetValue(expectedType, out formatterAndDelegate))
                {
                    var formatter = formatterResolver.GetFormatterDynamic(expectedType);
                    if (formatter == null)
                    {
                        ThrowHelper.ThrowFormatterNotRegisteredException(expectedType, formatterResolver);
                    }

                    var formatterType = typeof(IMessagePackFormatter <>).GetCachedGenericType(expectedType);
                    var param0        = Expression.Parameter(typeof(object), "formatter");
                    var param1        = Expression.Parameter(typeof(MessagePackWriter).MakeByRefType(), "writer");
                    var param2        = Expression.Parameter(typeof(int).MakeByRefType(), "idx");
                    var param3        = Expression.Parameter(typeof(object), "value");
                    var param4        = Expression.Parameter(typeof(IFormatterResolver), "formatterResolver");

                    var serializeMethodInfo = formatterType.GetRuntimeMethod("Serialize", new[] { typeof(MessagePackWriter).MakeByRefType(), typeof(int).MakeByRefType(), expectedType, typeof(IFormatterResolver) });

                    var body = Expression.Call(
                        Expression.Convert(param0, formatterType),
                        serializeMethodInfo,
                        param1,
                        param2,
                        expectedType.IsValueType ? Expression.Unbox(param3, expectedType) : Expression.Convert(param3, expectedType),
                        param4);

                    var lambda = Expression.Lambda <SerializeMethod>(body, param0, param1, param2, param3, param4).Compile();

                    formatterAndDelegate = new KeyValuePair <object, SerializeMethod>(formatter, lambda);
                    s_serializers.TryAdd(expectedType, formatterAndDelegate);
                }
            }
        }
コード例 #7
0
        protected int SerializeProperty <U>(ref byte[] bytes, int offset, string name, U contents, IFormatterResolver formatterResolver, Func <object> valueFormatterHandler = null)
        {
            var initialSize = offset;

            offset += formatterResolver.GetFormatter <string>().Serialize(ref bytes, offset, name, formatterResolver);

            if (contents == null)
            {
                offset += MessagePackBinary.WriteNil(ref bytes, offset);
                return(offset - initialSize);
            }

            // element value

            var fromResolver = formatterResolver.GetFormatterDynamic(contents.GetType());
            var fromHandler  = valueFormatterHandler != null?valueFormatterHandler() : fromResolver;

            var primaryElementFormatter = fromResolver == null?valueFormatterHandler() : fromResolver;

            offset += SerializeField(ref bytes, offset, contents, primaryElementFormatter, formatterResolver);


            return(offset - initialSize);
        }
コード例 #8
0
        public int Serialize(ref byte[] bytes, int offset, object value, IFormatterResolver formatterResolver)
        {
            if (value == null)
            {
                return(MessagePackBinary.WriteNil(ref bytes, offset));
            }

            var type = value.GetType();
            var ti   = type.GetTypeInfo();

            if ((PrimitiveObjectFormatter.IsSupportedType(type, ti, value) &&
                 !(value is DateTime) &&
                 !(value is IDictionary) &&
                 !(value is ICollection)) ||
                ti.IsAnonymous())
            {
                return(DynamicObjectTypeFallbackFormatter.Instance.Serialize(ref bytes, offset, value, formatterResolver));
            }

            var typeName = BuildTypeName(type);

            if (blacklistCheck.Contains(type.FullName))
            {
                throw new InvalidOperationException("Type is in blacklist:" + type.FullName);
            }

            KeyValuePair <object, SerializeMethod> formatterAndDelegate;

            if (type == typeof(object))
            {
                formatterAndDelegate = new KeyValuePair <object, SerializeMethod>(null, (object p1, ref byte[] p2, int p3, object p4, IFormatterResolver p5) => 0);
            }
            else
            {
                lock (serializers)
                {
                    if (!serializers.TryGetValue(type, out formatterAndDelegate))
                    {
                        var formatter = formatterResolver.GetFormatterDynamic(type);
                        if (formatter == null)
                        {
                            throw new FormatterNotRegisteredException(type.FullName + " is not registered in this resolver. resolver:" + formatterResolver.GetType().Name);
                        }

                        var formatterType = typeof(IMessagePackFormatter <>).MakeGenericType(type);
                        var param0        = Expression.Parameter(typeof(object), "formatter");
                        var param1        = Expression.Parameter(typeof(byte[]).MakeByRefType(), "bytes");
                        var param2        = Expression.Parameter(typeof(int), "offset");
                        var param3        = Expression.Parameter(typeof(object), "value");
                        var param4        = Expression.Parameter(typeof(IFormatterResolver), "formatterResolver");

                        var serializeMethodInfo = formatterType.GetRuntimeMethod("Serialize", new[] { typeof(byte[]).MakeByRefType(), typeof(int), type, typeof(IFormatterResolver) });

                        var body = Expression.Call(
                            Expression.Convert(param0, formatterType),
                            serializeMethodInfo,
                            param1,
                            param2,
                            ti.IsValueType ? Expression.Unbox(param3, type) : Expression.Convert(param3, type),
                            param4);

                        var lambda = Expression.Lambda <SerializeMethod>(body, param0, param1, param2, param3, param4).Compile();

                        formatterAndDelegate = new KeyValuePair <object, SerializeMethod>(formatter, lambda);

                        serializers[type] = formatterAndDelegate;
                    }
                }
            }
            // mark as extension with code 100
            var startOffset = offset;

            offset += 6; // mark will be written at the end, when size is known
            offset += MessagePackBinary.WriteString(ref bytes, offset, typeName);
            offset += formatterAndDelegate.Value(formatterAndDelegate.Key, ref bytes, offset, value, formatterResolver);
            MessagePackBinary.WriteExtensionFormatHeaderForceExt32Block(ref bytes, startOffset, (sbyte)TypelessFormatter.ExtensionTypeCode, offset - startOffset - 6);
            return(offset - startOffset);
        }
コード例 #9
0
        /// <summary>
        /// Does not support deserializing of anonymous types
        /// Type should be covered by preceeding resolvers in complex/standard resolver.
        /// </summary>
        private object DeserializeByTypeName(ArraySegment <byte> typeName, ref MessagePackReader byteSequence, MessagePackSerializerOptions options)
        {
            // try get type with assembly name, throw if not found
            Type type;

            if (!this.typeCache.TryGetValue(typeName, out type))
            {
                var buffer = new byte[typeName.Count];
                Buffer.BlockCopy(typeName.Array, typeName.Offset, buffer, 0, buffer.Length);
                var str = StringEncoding.UTF8.GetString(buffer);
                type = this.BindToType(str);
                if (type == null)
                {
                    if (IsMscorlib && str.Contains("System.Private.CoreLib"))
                    {
                        str  = str.Replace("System.Private.CoreLib", "mscorlib");
                        type = Type.GetType(str, true); // throw
                    }
                    else if (!IsMscorlib && str.Contains("mscorlib"))
                    {
                        str  = str.Replace("mscorlib", "System.Private.CoreLib");
                        type = Type.GetType(str, true); // throw
                    }
                    else
                    {
                        type = Type.GetType(str, true); // re-throw
                    }
                }

                this.typeCache.TryAdd(buffer, type);
            }

            KeyValuePair <object, DeserializeMethod> formatterAndDelegate;

            if (!this.deserializers.TryGetValue(type, out formatterAndDelegate))
            {
                lock (this.deserializers)
                {
                    if (!this.deserializers.TryGetValue(type, out formatterAndDelegate))
                    {
                        TypeInfo ti = type.GetTypeInfo();

                        IFormatterResolver resolver = options.Resolver;
                        var formatter = resolver.GetFormatterDynamic(type);
                        if (formatter == null)
                        {
                            throw new FormatterNotRegisteredException(type.FullName + " is not registered in this resolver. resolver:" + resolver.GetType().Name);
                        }

                        Type formatterType         = typeof(IMessagePackFormatter <>).MakeGenericType(type);
                        ParameterExpression param0 = Expression.Parameter(typeof(object), "formatter");
                        ParameterExpression param1 = Expression.Parameter(typeof(MessagePackReader).MakeByRefType(), "reader");
                        ParameterExpression param2 = Expression.Parameter(typeof(MessagePackSerializerOptions), "options");

                        MethodInfo deserializeMethodInfo = formatterType.GetRuntimeMethod("Deserialize", new[] { typeof(MessagePackReader).MakeByRefType(), typeof(MessagePackSerializerOptions) });

                        MethodCallExpression deserialize = Expression.Call(
                            Expression.Convert(param0, formatterType),
                            deserializeMethodInfo,
                            param1,
                            param2);

                        Expression body = deserialize;
                        if (ti.IsValueType)
                        {
                            body = Expression.Convert(deserialize, typeof(object));
                        }

                        DeserializeMethod lambda = Expression.Lambda <DeserializeMethod>(body, param0, param1, param2).Compile();

                        formatterAndDelegate = new KeyValuePair <object, DeserializeMethod>(formatter, lambda);
                        this.deserializers.TryAdd(type, formatterAndDelegate);
                    }
                }
            }

            return(formatterAndDelegate.Value(formatterAndDelegate.Key, ref byteSequence, options));
        }
コード例 #10
0
        public void Serialize(ref MessagePackWriter writer, object value, MessagePackSerializerOptions options)
        {
            if (value == null)
            {
                writer.WriteNil();
                return;
            }

            Type type = value.GetType();

            byte[] typeName;
            if (!this.typeNameCache.TryGetValue(type, out typeName))
            {
                if (BlacklistCheck.Contains(type.FullName))
                {
                    throw new InvalidOperationException("Type is in blacklist:" + type.FullName);
                }

                TypeInfo ti = type.GetTypeInfo();
                if (ti.IsAnonymous() || UseBuiltinTypes.Contains(type))
                {
                    typeName = null;
                }
                else
                {
                    typeName = StringEncoding.UTF8.GetBytes(this.BuildTypeName(type));
                }

                this.typeNameCache.TryAdd(type, typeName);
            }

            if (typeName == null)
            {
                Resolvers.TypelessFormatterFallbackResolver.Instance.GetFormatter <object>().Serialize(ref writer, value, options);
                return;
            }

            // don't use GetOrAdd for avoid closure capture.
            KeyValuePair <object, SerializeMethod> formatterAndDelegate;

            if (!this.serializers.TryGetValue(type, out formatterAndDelegate))
            {
                // double check locking...
                lock (this.serializers)
                {
                    if (!this.serializers.TryGetValue(type, out formatterAndDelegate))
                    {
                        TypeInfo ti = type.GetTypeInfo();

                        IFormatterResolver resolver = options.Resolver;
                        var formatter = resolver.GetFormatterDynamic(type);
                        if (formatter == null)
                        {
                            throw new FormatterNotRegisteredException(type.FullName + " is not registered in this resolver. resolver:" + resolver.GetType().Name);
                        }

                        Type formatterType         = typeof(IMessagePackFormatter <>).MakeGenericType(type);
                        ParameterExpression param0 = Expression.Parameter(typeof(object), "formatter");
                        ParameterExpression param1 = Expression.Parameter(typeof(MessagePackWriter).MakeByRefType(), "writer");
                        ParameterExpression param2 = Expression.Parameter(typeof(object), "value");
                        ParameterExpression param3 = Expression.Parameter(typeof(MessagePackSerializerOptions), "options");

                        MethodInfo serializeMethodInfo = formatterType.GetRuntimeMethod("Serialize", new[] { typeof(MessagePackWriter).MakeByRefType(), type, typeof(MessagePackSerializerOptions) });

                        MethodCallExpression body = Expression.Call(
                            Expression.Convert(param0, formatterType),
                            serializeMethodInfo,
                            param1,
                            ti.IsValueType ? Expression.Unbox(param2, type) : Expression.Convert(param2, type),
                            param3);

                        SerializeMethod lambda = Expression.Lambda <SerializeMethod>(body, param0, param1, param2, param3).Compile();

                        formatterAndDelegate = new KeyValuePair <object, SerializeMethod>(formatter, lambda);
                        this.serializers.TryAdd(type, formatterAndDelegate);
                    }
                }
            }

            // mark will be written at the end, when size is known
            using (var scratch = new Nerdbank.Streams.Sequence <byte>())
            {
                MessagePackWriter scratchWriter = writer.Clone(scratch);
                scratchWriter.WriteString(typeName);
                formatterAndDelegate.Value(formatterAndDelegate.Key, ref scratchWriter, value, options);
                scratchWriter.Flush();

                // mark as extension with code 100
                writer.WriteExtensionFormat(new ExtensionResult((sbyte)TypelessFormatter.ExtensionTypeCode, scratch.AsReadOnlySequence));
            }
        }
コード例 #11
0
 protected override bool CanReadType(Type type)
 {
     return(_resolver.GetFormatterDynamic(type) != null && base.CanReadType(type));
 }
コード例 #12
0
 protected override bool CanWriteType(Type type)
 {
     return(_resolver.GetFormatterDynamic(type) != null);
 }
コード例 #13
0
 public override bool CanReadType(Type type)
 {
     return(_resolver.GetFormatterDynamic(type) != null);
 }
コード例 #14
0
        /// <summary>
        /// Does not support deserializing of anonymous types
        /// Type should be covered by preceeding resolvers in complex/standard resolver
        /// </summary>
        private object DeserializeByTypeName(ArraySegment <byte> typeName, byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize)
        {
            // try get type with assembly name, throw if not found
            Type type;

            if (!typeCache.TryGetValue(typeName, out type))
            {
                var buffer = new byte[typeName.Count];
                Buffer.BlockCopy(typeName.Array, typeName.Offset, buffer, 0, buffer.Length);
                var str = StringEncoding.UTF8.GetString(buffer);
                type = BindToType(str);
                if (type == null)
                {
                    if (isMscorlib && str.Contains("System.Private.CoreLib"))
                    {
                        str  = str.Replace("System.Private.CoreLib", "mscorlib");
                        type = Type.GetType(str, true); // throw
                    }
                    else if (!isMscorlib && str.Contains("mscorlib"))
                    {
                        str  = str.Replace("mscorlib", "System.Private.CoreLib");
                        type = Type.GetType(str, true); // throw
                    }
                    else
                    {
                        type = Type.GetType(str, true); // re-throw
                    }
                }
                typeCache.TryAdd(buffer, type);
            }

            KeyValuePair <object, DeserializeMethod> formatterAndDelegate;

            if (!deserializers.TryGetValue(type, out formatterAndDelegate))
            {
                lock (deserializers)
                {
                    if (!deserializers.TryGetValue(type, out formatterAndDelegate))
                    {
                        var ti = type.GetTypeInfo();

                        var formatter = formatterResolver.GetFormatterDynamic(type);
                        if (formatter == null)
                        {
                            throw new FormatterNotRegisteredException(type.FullName + " is not registered in this resolver. resolver:" + formatterResolver.GetType().Name);
                        }

                        var formatterType = typeof(IMessagePackFormatter <>).MakeGenericType(type);
                        var param0        = Expression.Parameter(typeof(object), "formatter");
                        var param1        = Expression.Parameter(typeof(byte[]), "bytes");
                        var param2        = Expression.Parameter(typeof(int), "offset");
                        var param3        = Expression.Parameter(typeof(IFormatterResolver), "formatterResolver");
                        var param4        = Expression.Parameter(typeof(int).MakeByRefType(), "readSize");

                        var deserializeMethodInfo = formatterType.GetRuntimeMethod("Deserialize", new[] { typeof(byte[]), typeof(int), typeof(IFormatterResolver), typeof(int).MakeByRefType() });

                        var deserialize = Expression.Call(
                            Expression.Convert(param0, formatterType),
                            deserializeMethodInfo,
                            param1,
                            param2,
                            param3,
                            param4);

                        Expression body = deserialize;
                        if (ti.IsValueType)
                        {
                            body = Expression.Convert(deserialize, typeof(object));
                        }
                        var lambda = Expression.Lambda <DeserializeMethod>(body, param0, param1, param2, param3, param4).Compile();

                        formatterAndDelegate = new KeyValuePair <object, DeserializeMethod>(formatter, lambda);
                        deserializers.TryAdd(type, formatterAndDelegate);
                    }
                }
            }

            return(formatterAndDelegate.Value(formatterAndDelegate.Key, bytes, offset, formatterResolver, out readSize));
        }
コード例 #15
0
        public int Serialize(ref byte[] bytes, int offset, object value, IFormatterResolver formatterResolver)
        {
            if (value == null)
            {
                return(MessagePackBinary.WriteNil(ref bytes, offset));
            }

            var type = value.GetType();

            byte[] typeName;
            if (!typeNameCache.TryGetValue(type, out typeName))
            {
                if (blacklistCheck.Contains(type.FullName))
                {
                    throw new InvalidOperationException("Type is in blacklist:" + type.FullName);
                }

                var ti = type.GetTypeInfo();
                if (ti.IsAnonymous() || useBuiltinTypes.Contains(type))
                {
                    typeName = null;
                }
                else
                {
                    typeName = StringEncoding.UTF8.GetBytes(BuildTypeName(type));
                }
                typeNameCache.TryAdd(type, typeName);
            }

            if (typeName == null)
            {
                return(Resolvers.TypelessFormatterFallbackResolver.Instance.GetFormatter <object>().Serialize(ref bytes, offset, value, formatterResolver));
            }

            // don't use GetOrAdd for avoid closure capture.
            KeyValuePair <object, SerializeMethod> formatterAndDelegate;

            if (!serializers.TryGetValue(type, out formatterAndDelegate))
            {
                lock (serializers) // double check locking...
                {
                    if (!serializers.TryGetValue(type, out formatterAndDelegate))
                    {
                        var ti = type.GetTypeInfo();

                        var formatter = formatterResolver.GetFormatterDynamic(type);
                        if (formatter == null)
                        {
                            throw new FormatterNotRegisteredException(type.FullName + " is not registered in this resolver. resolver:" + formatterResolver.GetType().Name);
                        }

                        var formatterType = typeof(IMessagePackFormatter <>).MakeGenericType(type);
                        var param0        = Expression.Parameter(typeof(object), "formatter");
                        var param1        = Expression.Parameter(typeof(byte[]).MakeByRefType(), "bytes");
                        var param2        = Expression.Parameter(typeof(int), "offset");
                        var param3        = Expression.Parameter(typeof(object), "value");
                        var param4        = Expression.Parameter(typeof(IFormatterResolver), "formatterResolver");

                        var serializeMethodInfo = formatterType.GetRuntimeMethod("Serialize", new[] { typeof(byte[]).MakeByRefType(), typeof(int), type, typeof(IFormatterResolver) });

                        var body = Expression.Call(
                            Expression.Convert(param0, formatterType),
                            serializeMethodInfo,
                            param1,
                            param2,
                            ti.IsValueType ? Expression.Unbox(param3, type) : Expression.Convert(param3, type),
                            param4);

                        var lambda = Expression.Lambda <SerializeMethod>(body, param0, param1, param2, param3, param4).Compile();

                        formatterAndDelegate = new KeyValuePair <object, SerializeMethod>(formatter, lambda);
                        serializers.TryAdd(type, formatterAndDelegate);
                    }
                }
            }

            // mark as extension with code 100
            var startOffset = offset;

            offset += 6; // mark will be written at the end, when size is known
            offset += MessagePackBinary.WriteStringBytes(ref bytes, offset, typeName);
            offset += formatterAndDelegate.Value(formatterAndDelegate.Key, ref bytes, offset, value, formatterResolver);
            MessagePackBinary.WriteExtensionFormatHeaderForceExt32Block(ref bytes, startOffset, (sbyte)TypelessFormatter.ExtensionTypeCode, offset - startOffset - 6);
            return(offset - startOffset);
        }