static KeyframeFormatter()
        {
            Is_In_2018_1_Or_Above = typeof(Keyframe).GetProperty("weightedMode") != null;

            if (Is_In_2018_1_Or_Above)
            {
                if (EmitUtilities.CanEmit)
                {
                    Formatter = (IFormatter <Keyframe>)FormatterEmitter.GetEmittedFormatter(typeof(Keyframe), SerializationPolicies.Everything);
                }
                else
                {
                    Formatter = new ReflectionFormatter <Keyframe>(SerializationPolicies.Everything);
                }
            }
        }
        private static IFormatter CreateFormatter(Type type, ISerializationPolicy policy)
        {
            if (FormatterUtilities.IsPrimitiveType(type))
            {
                throw new ArgumentException("Cannot create formatters for a primitive type like " + type.Name);
            }

            // First call formatter locators before checking for registered formatters
            for (int i = 0; i < FormatterLocators.Count; i++)
            {
                try
                {
                    IFormatter result;
                    if (FormatterLocators[i].LocatorInstance.TryGetFormatter(type, FormatterLocationStep.BeforeRegisteredFormatters, policy, out result))
                    {
                        return(result);
                    }
                }
                catch (TargetInvocationException ex)
                {
                    throw ex;
                }
                catch (TypeInitializationException ex)
                {
                    throw ex;
                }
#pragma warning disable CS0618 // Type or member is obsolete
                catch (ExecutionEngineException ex)
#pragma warning restore CS0618 // Type or member is obsolete
                {
                    throw ex;
                }
                catch (Exception ex)
                {
                    Debug.LogException(new Exception("Exception was thrown while calling FormatterLocator " + FormatterLocators[i].GetType().FullName + ".", ex));
                }
            }

            // Then check for valid registered formatters
            for (int i = 0; i < FormatterInfos.Count; i++)
            {
                var info = FormatterInfos[i];

                Type formatterType = null;

                if (type == info.TargetType)
                {
                    formatterType = info.FormatterType;
                }
                else if (info.FormatterType.IsGenericType && info.TargetType.IsGenericParameter)
                {
                    Type[] inferredArgs;

                    if (info.FormatterType.TryInferGenericParameters(out inferredArgs, type))
                    {
                        formatterType = info.FormatterType.GetGenericTypeDefinition().MakeGenericType(inferredArgs);
                    }
                }
                else if (type.IsGenericType && info.FormatterType.IsGenericType && info.TargetType.IsGenericType && type.GetGenericTypeDefinition() == info.TargetType.GetGenericTypeDefinition())
                {
                    Type[] args = type.GetGenericArguments();

                    if (info.FormatterType.AreGenericConstraintsSatisfiedBy(args))
                    {
                        formatterType = info.FormatterType.GetGenericTypeDefinition().MakeGenericType(args);
                    }
                }

                if (formatterType != null)
                {
                    var instance = GetFormatterInstance(formatterType);

                    if (instance == null)
                    {
                        continue;
                    }

                    if (info.AskIfCanFormatTypes && !((IAskIfCanFormatTypes)instance).CanFormatType(type))
                    {
                        continue;
                    }

                    return(instance);
                }
            }

            // Then call formatter locators after checking for registered formatters
            for (int i = 0; i < FormatterLocators.Count; i++)
            {
                try
                {
                    IFormatter result;
                    if (FormatterLocators[i].LocatorInstance.TryGetFormatter(type, FormatterLocationStep.AfterRegisteredFormatters, policy, out result))
                    {
                        return(result);
                    }
                }
                catch (TargetInvocationException ex)
                {
                    throw ex;
                }
                catch (TypeInitializationException ex)
                {
                    throw ex;
                }
#pragma warning disable CS0618 // Type or member is obsolete
                catch (ExecutionEngineException ex)
#pragma warning restore CS0618 // Type or member is obsolete
                {
                    throw ex;
                }
                catch (Exception ex)
                {
                    Debug.LogException(new Exception("Exception was thrown while calling FormatterLocator " + FormatterLocators[i].GetType().FullName + ".", ex));
                }
            }

            // If we can, emit a formatter to handle serialization of this object
            {
                if (EmitUtilities.CanEmit)
                {
                    var result = FormatterEmitter.GetEmittedFormatter(type, policy);
                    if (result != null)
                    {
                        return(result);
                    }
                }
            }

            if (EmitUtilities.CanEmit)
            {
                Debug.LogWarning("Fallback to reflection for type " + type.Name + " when emit is possible on this platform.");
            }

            // Finally, we fall back to a reflection-based formatter if nothing else has been found
            return((IFormatter)Activator.CreateInstance(typeof(ReflectionFormatter <>).MakeGenericType(type)));
        }