protected ObjectReflectionMessagePackSerializer(Type type, SerializationContext context, SerializingMember[] members)
            : base(type, (context ?? SerializationContext.Default).CompatibilityOptions.PackerCompatibilityOptions)
        {
            if (type.GetIsAbstract() || type.GetIsInterface())
            {
                throw SerializationExceptions.NewNotSupportedBecauseCannotInstanciateAbstractType(type);
            }

            this._createInstance = () => Activator.CreateInstance(type);

            //Expression.Lambda<Func<T>>(
            //    typeof(T).GetIsValueType()
            //        ? Expression.Default(typeof(T)) as Expression
            //        : Expression.New(typeof(T).GetConstructor(ReflectionAbstractions.EmptyTypes))
            //    ).Compile();
            var isPackable   = typeof(IPackable).IsAssignableFrom(type);
            var isUnpackable = typeof(IUnpackable).IsAssignableFrom(type);

            if (isPackable && isUnpackable)
            {
                this._memberSerializers = null;
                this._indexMap          = null;
                this._isCollection      = null;
                this._nilImplications   = null;
                this._memberNames       = null;
            }
            else
            {
                this._memberSerializers =
                    members.Select(
                        m => m.Member == null ? NullSerializer.Instance : context.GetSerializer(m.Member.GetMemberValueType())).ToArray
                    (

                    );
                this._indexMap =
                    members
                    .Select((m, i) => new KeyValuePair <SerializingMember, int>(m, i))
                    .Where(kv => kv.Key.Member != null)
                    .ToDictionary(kv => kv.Key.Contract.Name, kv => kv.Value);

                this._isCollection =
                    members.Select(
                        m => m.Member == null ? CollectionTraits.NotCollection : m.Member.GetMemberValueType().GetCollectionTraits()).
                    Select(t => t.CollectionType != CollectionKind.NotCollection).ToArray();

                // NilImplication validity check
                foreach (var member in members)
                {
                    switch (member.Contract.NilImplication)
                    {
                    case NilImplication.Null:
                    {
                        if (member.Member.GetMemberValueType().GetIsValueType() &&
                            Nullable.GetUnderlyingType(member.Member.GetMemberValueType()) == null)
                        {
                            throw SerializationExceptions.NewValueTypeCannotBeNull(
                                      member.Contract.Name, member.Member.GetMemberValueType(), member.Member.DeclaringType
                                      );
                        }

                        if (!member.Member.CanSetValue())
                        {
                            throw SerializationExceptions.NewReadOnlyMemberItemsMustNotBeNull(member.Contract.Name);
                        }

                        break;
                    }
                    }
                }

                this._nilImplications = members.Select(m => m.Contract.NilImplication).ToArray();
                this._memberNames     = members.Select(m => m.Contract.Name).ToArray();
            }

            if (isPackable)
            {
                this._packToMessage = (target, packer, packingOptions) =>
                {
                    ((IPackable)target).PackToMessage(packer, packingOptions);
                    //typeof(T).GetInterfaceMap(typeof(IPackable)).TargetMethods.Single().Invoke(target, new object[] { packer, packingOptions });
                };
                this._memberGetters = null;
            }
            else
            {
                this._packToMessage = null;
                this._memberGetters =
                    members.Select <SerializingMember, Func <object, object> >(
                        m => m.Member == null ? (target => null)
                        : CreateMemberGetter(m)).ToArray();
            }

            if (isUnpackable)
            {
                this._unpackFromMessage = delegate(ref object target, Unpacker value)
                {
                    ((IUnpackable)target).UnpackFromMessage(value);
                };

                this._memberSetters = null;
            }
            else
            {
                this._unpackFromMessage = null;

                this._memberSetters =
                    members.Select(
                        m =>
                        m.Member == null
                        ? delegate(ref object target, object memberValue) { }
                :
                        m.Member.CanSetValue()
                        ? CreateMemberSetter(m)
                        : UnpackHelpers.IsReadOnlyAppendableCollectionMember(m.Member)
                        ? default(MemberSetter)
                        : ThrowGetOnlyMemberIsInvalid(m.Member)
                        ).ToArray();
            }
        }
        protected ObjectReflectionMessagePackSerializer(Type type, SerializationContext context, SerializingMember[] members)
            : base(type, (context ?? SerializationContext.Default).CompatibilityOptions.PackerCompatibilityOptions)
        {
            if (type.GetIsAbstract() || type.GetIsInterface())
            {
                throw SerializationExceptions.NewNotSupportedBecauseCannotInstanciateAbstractType(type);
            }

                this._createInstance = () => Activator.CreateInstance(type);

            //Expression.Lambda<Func<T>>(
            //    typeof(T).GetIsValueType()
            //        ? Expression.Default(typeof(T)) as Expression
            //        : Expression.New(typeof(T).GetConstructor(ReflectionAbstractions.EmptyTypes))
            //    ).Compile();
            var isPackable = typeof(IPackable).IsAssignableFrom(type);
            var isUnpackable = typeof(IUnpackable).IsAssignableFrom(type);

            if (isPackable && isUnpackable)
            {
                this._memberSerializers = null;
                this._indexMap = null;
                this._isCollection = null;
                this._nilImplications = null;
                this._memberNames = null;
            }
            else
            {
                this._memberSerializers =
                    members.Select(
                        m => m.Member == null ? NullSerializer.Instance : context.GetSerializer(m.Member.GetMemberValueType())).ToArray
                        (

                        );
                this._indexMap =
                    members
                        .Select((m, i) => new KeyValuePair<SerializingMember, int>(m, i))
                        .Where(kv => kv.Key.Member != null)
                        .ToDictionary(kv => kv.Key.Contract.Name, kv => kv.Value);

                this._isCollection =
                    members.Select(
                        m => m.Member == null ? CollectionTraits.NotCollection : m.Member.GetMemberValueType().GetCollectionTraits()).
                        Select(t => t.CollectionType != CollectionKind.NotCollection).ToArray();

                // NilImplication validity check
                foreach (var member in members)
                {
                    switch (member.Contract.NilImplication)
                    {
                        case NilImplication.Null:
                            {
                                if (member.Member.GetMemberValueType().GetIsValueType() &&
                                    Nullable.GetUnderlyingType(member.Member.GetMemberValueType()) == null)
                                {
                                    throw SerializationExceptions.NewValueTypeCannotBeNull(
                                        member.Contract.Name, member.Member.GetMemberValueType(), member.Member.DeclaringType
                                    );
                                }

                                if (!member.Member.CanSetValue())
                                {
                                    throw SerializationExceptions.NewReadOnlyMemberItemsMustNotBeNull(member.Contract.Name);
                                }

                                break;
                            }
                    }
                }

                this._nilImplications = members.Select(m => m.Contract.NilImplication).ToArray();
                this._memberNames = members.Select(m => m.Contract.Name).ToArray();
            }

            if (isPackable)
            {
                this._packToMessage = (target, packer, packingOptions) =>
                {
                    ((IPackable)target).PackToMessage(packer, packingOptions);
                    //typeof(T).GetInterfaceMap(typeof(IPackable)).TargetMethods.Single().Invoke(target, new object[] { packer, packingOptions });
                };
                this._memberGetters = null;
            }
            else
            {
                this._packToMessage = null;
                this._memberGetters =
                    members.Select<SerializingMember,Func<object,object>>(
                    m => m.Member == null ? (target => null)
                        : CreateMemberGetter(m)).ToArray();
            }

            if (isUnpackable)
            {
                this._unpackFromMessage = delegate(ref object target, Unpacker value)
                {
                    ((IUnpackable)target).UnpackFromMessage(value);
                };

                this._memberSetters = null;
            }
            else
            {
                this._unpackFromMessage = null;

                this._memberSetters =
                    members.Select(
                        m =>
                        m.Member == null
                        ? delegate(ref object target, object memberValue) { }
                :
                  m.Member.CanSetValue()
                        ? CreateMemberSetter(m)
                        : UnpackHelpers.IsReadOnlyAppendableCollectionMember(m.Member)
                        ? default(MemberSetter)
                        : ThrowGetOnlyMemberIsInvalid(m.Member)
                ).ToArray();
            }
        }
        protected ObjectExpressionMessagePackSerializer(SerializationContext context, SerializingMember[] members)
            : base((context ?? SerializationContext.Default).CompatibilityOptions.PackerCompatibilityOptions)
        {
            if (typeof(T).GetIsAbstract() || typeof(T).GetIsInterface())
            {
                throw SerializationExceptions.NewNotSupportedBecauseCannotInstanciateAbstractType(typeof(T));
            }

            this._createInstance =
                Expression.Lambda <Func <T> >(
                    typeof(T).GetIsValueType()
                                                ? Expression.Default(typeof(T)) as Expression
                                                : Expression.New(typeof(T).GetConstructor(ReflectionAbstractions.EmptyTypes))
                    ).Compile();
            var isPackable   = typeof(IPackable).IsAssignableFrom(typeof(T));
            var isUnpackable = typeof(IUnpackable).IsAssignableFrom(typeof(T));

            var targetParameter = Expression.Parameter(typeof(T), "target");

            if (isPackable && isUnpackable)
            {
                this._memberSerializers = null;
                this._indexMap          = null;
                this._isCollection      = null;
                this._nilImplications   = null;
                this._memberNames       = null;
            }
            else
            {
                this._memberSerializers =
                    members.Select(
                        m => m.Member == null ? NullSerializer.Instance : context.GetSerializer(m.Member.GetMemberValueType())).ToArray
                    (

                    );
                this._indexMap =
                    members
                    .Zip(Enumerable.Range(0, members.Length), (m, i) => new KeyValuePair <SerializingMember, int>(m, i))
                    .Where(kv => kv.Key.Member != null)
                    .ToDictionary(kv => kv.Key.Contract.Name, kv => kv.Value);

                this._isCollection =
                    members.Select(
                        m => m.Member == null ? CollectionTraits.NotCollection : m.Member.GetMemberValueType().GetCollectionTraits()).
                    Select(t => t.CollectionType != CollectionKind.NotCollection).ToArray();

                // NilImplication validity check
                foreach (var member in members)
                {
                    switch (member.Contract.NilImplication)
                    {
                    case NilImplication.Null:
                    {
                        if (member.Member.GetMemberValueType().GetIsValueType() &&
                            Nullable.GetUnderlyingType(member.Member.GetMemberValueType()) == null)
                        {
                            throw SerializationExceptions.NewValueTypeCannotBeNull(
                                      member.Contract.Name, member.Member.GetMemberValueType(), member.Member.DeclaringType
                                      );
                        }

                        if (!member.Member.CanSetValue())
                        {
                            throw SerializationExceptions.NewReadOnlyMemberItemsMustNotBeNull(member.Contract.Name);
                        }

                        break;
                    }
                    }
                }

                this._nilImplications = members.Select(m => m.Contract.NilImplication).ToArray();
                this._memberNames     = members.Select(m => m.Contract.Name).ToArray();
            }

            if (isPackable)
            {
                var packerParameter  = Expression.Parameter(typeof(Packer), "packer");
                var optionsParameter = Expression.Parameter(typeof(PackingOptions), "options");
                this._packToMessage =
                    Expression.Lambda <Action <T, Packer, PackingOptions> >(
                        Expression.Call(
                            targetParameter,
                            typeof(T).GetInterfaceMap(typeof(IPackable)).TargetMethods.Single(),
                            packerParameter,
                            optionsParameter
                            ),
                        targetParameter, packerParameter, optionsParameter
                        ).Compile();
                this._memberGetters = null;
            }
            else
            {
                this._packToMessage = null;
                this._memberGetters =
                    members.Select(
                        m =>
                        m.Member == null
                                                ? Expression.Lambda <Func <T, object> >(
                            Expression.Constant(null),
                            targetParameter
                            ).Compile()
                                                : CreateMemberGetter(targetParameter, m)
                        ).ToArray();
            }

            var refTargetParameter = Expression.Parameter(typeof(T).MakeByRefType(), "target");

            if (isUnpackable)
            {
                var unpackerParameter = Expression.Parameter(typeof(Unpacker), "unpacker");
                this._unpackFromMessage =
                    Expression.Lambda <UnpackFromMessageInvocation>(
                        Expression.Call(
                            refTargetParameter,
                            typeof(T).GetInterfaceMap(typeof(IUnpackable)).TargetMethods.Single(),
                            unpackerParameter
                            ),
                        refTargetParameter, unpackerParameter
                        ).Compile();
                this._memberSetters = null;
            }
            else
            {
                this._unpackFromMessage = null;

                var valueParameter = Expression.Parameter(typeof(object), "value");
                this._memberSetters =
                    members.Select(
                        m =>
                        m.Member == null
                                                ? Expression.Lambda <MemberSetter>(
                            Expression.Empty(),
                            refTargetParameter,
                            valueParameter
                            ).Compile()
                                                : m.Member.CanSetValue()
                                                ? Expression.Lambda <MemberSetter>(
                            Expression.Assign(
                                Expression.PropertyOrField(
                                    refTargetParameter,
                                    m.Member.Name
                                    ),
                                Expression.Call(
                                    Metadata._UnpackHelpers.ConvertWithEnsuringNotNull_1Method.MakeGenericMethod(m.Member.GetMemberValueType()),
                                    valueParameter,
                                    Expression.Constant(m.Member.Name),
                                    Expression.Call(                                     // Using RuntimeTypeHandle to avoid WinRT expression tree issue.
                                        null,
                                        Metadata._Type.GetTypeFromHandle,
                                        Expression.Constant(m.Member.DeclaringType.TypeHandle)
                                        )
                                    )
                                ),
                            refTargetParameter,
                            valueParameter
                            ).Compile()
                                                : UnpackHelpers.IsReadOnlyAppendableCollectionMember(m.Member)
                                                ? default(MemberSetter)
                                                : ThrowGetOnlyMemberIsInvalid(m.Member)
                        ).ToArray();
            }
        }