private void ValidateValue(object value, ICustomAttributeProvider provider)
        {
            if (value == null)
            {
                if (rejectNullValue)
                {
                    host.Assert(false, "value to be checked must not be null");
                }
                else
                {
                    return;
                }
            }

            CheckEnum(value);

            object obj = (object)value;
            Type   t   = value.GetType();

            marshaler.EnterContext();
            FieldInfo[] fields = t.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
            marshaler.DefineSymbols(fields, obj);
            if (symbolStore != null)
            {
                foreach (var symbolEntry in symbolStore)
                {
                    marshaler.DefineSymbol(symbolEntry.Key, symbolEntry.Value);
                }
            }
            foreach (FieldInfo field in fields)
            {
                if (field.GetValue(obj) == null)
                {
                    if (rejectNullValue)
                    {
                        host.Assert(false, "value of field '{0}' in the type '{1}' must not be null", field.Name, t.Name);
                    }
                    else
                    {
                        return;
                    }
                }

                Type ft = field.FieldType;

                if (ft.IsArray)
                {
                    int size, length;

                    IList <int> sizes, lengths;
                    marshaler.GetMultipleAdvocatedSizes(new MarshalingDescriptor(ft, field, t), out sizes, out lengths);

                    size   = sizes[0];
                    length = lengths[0];

                    object fv = field.GetValue(obj);
                    if (fv != null)
                    {
                        int actualSize;
                        if (ft.IsArray)
                        {
                            actualSize = ((Array)fv).GetLength(0);
                        }
                        else
                        {
                            actualSize = GetSequenceLength(ft, fv);
                        }
                        if (actualSize > size)
                        {
                            host.Assert(false,
                                        "validating value of type '{0}': advocated size of field '{1} is smaller than the actual size (advocated == {2}, actual == {3}",
                                        t, field, size, actualSize);
                        }
                    }
                }
            }

            CheckPossibleValue(value, provider);

            marshaler.ExitContext();

            List <MethodInfo> ms;

            if (validators.TryGetValue(t, out (ms)))
            {
                foreach (MethodInfo m in ms)
                {
                    object[] args = new object[] { obj };
                    try
                    {
                        m.Invoke(this, args);
                    }
                    catch (TargetInvocationException e)
                    {
                        throw e.InnerException;
                    }
                    if (m.GetParameters()[0].ParameterType.IsByRef)
                    {
                        obj = args[0];
                    }
                }
            }
        }