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))); }
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); } bool canSelfFormat = type.ImplementsOrInherits(typeof(ISelfFormatter)); // If the type should always self format, there is no need to explore further. // Otherwise, we go through the below checks first to see whether a custom // formatter is defined. if (canSelfFormat && type.IsDefined <AlwaysFormatsSelfAttribute>()) { return((IFormatter)Activator.CreateInstance(typeof(SelfFormatterFormatter <>).MakeGenericType(type))); } // First, allow the FormatterResolve event to resolve the formatter if possible // We always hold the lock in the CreateFormatter method, so we can safely // invoke the event without worrying about other threads changing it. if (FormatterResolvePrivate != null) { Type genericInterface = typeof(IFormatter <>).MakeGenericType(type); foreach (var del in FormatterResolvePrivate.GetInvocationList()) { IFormatter result = del.Method.Invoke(del.Target, new object[] { type }) as IFormatter; if (result != null && result.GetType().ImplementsOrInherits(genericInterface)) { return(result); } } } // Then try to find a custom formatter { Type formatterType; if (CustomFormatterTypes.TryGetValue(type, out formatterType)) { return((IFormatter)Activator.CreateInstance(formatterType)); } } if (type.IsGenericType) { // Then try to find a custom generic formatter. // IE, if we're trying to serialize Dictionary<string, int>, we might have a formatter that declares it can handle // Dictionary<TKey, TValue>. If so, we can use that. Type genericTypeDefinition = type.GetGenericTypeDefinition(); Type formatterGenericTypeDefinition; if (CustomGenericFormatterTypes.TryGetValue(genericTypeDefinition, out formatterGenericTypeDefinition)) { var formatterType = formatterGenericTypeDefinition.MakeGenericType(type.GetGenericArguments()); return((IFormatter)Activator.CreateInstance(formatterType)); } } // Quick hack to support types derived from dictionary if (type.ImplementsOpenGenericClass(typeof(Dictionary <,>)) && type.GetConstructor(Type.EmptyTypes) != null) { var dictArgs = type.GetArgumentsOfInheritedOpenGenericClass(typeof(Dictionary <,>)); var formatterType = typeof(DerivedDictionaryFormatter <, ,>).MakeGenericType(type, dictArgs[0], dictArgs[1]); return((IFormatter)Activator.CreateInstance(formatterType)); } // If there were no custom formatters found, the type can format itself if (canSelfFormat) { return((IFormatter)Activator.CreateInstance(typeof(SelfFormatterFormatter <>).MakeGenericType(type))); } // Delegates get special behaviour, as they're weird if (typeof(Delegate).IsAssignableFrom(type)) { return((IFormatter)Activator.CreateInstance(typeof(DelegateFormatter <>).MakeGenericType(type))); } // Types get special behaviour, as they are often instances of special runtime types like System.MonoType which cannot be addressed at compile time. if (typeof(Type).IsAssignableFrom(type)) { return(new TypeFormatter()); } if (type.IsArray) { // Custom behaviour for all arrays that don't have specific custom formatters if (type.GetArrayRank() == 1) { if (FormatterUtilities.IsPrimitiveArrayType(type.GetElementType())) { return((IFormatter)Activator.CreateInstance(typeof(PrimitiveArrayFormatter <>).MakeGenericType(type.GetElementType()))); } else { return((IFormatter)Activator.CreateInstance(typeof(ArrayFormatter <>).MakeGenericType(type.GetElementType()))); } } else { return((IFormatter)Activator.CreateInstance(typeof(MultiDimensionalArrayFormatter <,>).MakeGenericType(type, type.GetElementType()))); } } // If the type implements ISerializable, use the SerializableFormatter if (type.ImplementsOrInherits(typeof(ISerializable))) { return((IFormatter)Activator.CreateInstance(typeof(SerializableFormatter <>).MakeGenericType(type))); } // If the type can be treated as a generic collection, do that { Type elementType; if (GenericCollectionFormatter.CanFormat(type, out elementType)) { return((IFormatter)Activator.CreateInstance(typeof(GenericCollectionFormatter <,>).MakeGenericType(type, elementType))); } } // If we can, emit a formatter to handle serialization of this object { if (EmitUtilities.CanEmit) { return(FormatterEmitter.GetEmittedFormatter(type, policy)); } } 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))); }