private static Func <object, object> GetCastDelegate(Type from, Type to)
        {
            Func <object, object> castDelegate;

            if (!WeakCastLookup.TryGetInnerValue(from, to, out castDelegate))
            {
                castDelegate = TypeExtensions.GetCastMethodDelegate(from, to);
                WeakCastLookup.AddInner(from, to, castDelegate);
            }
            return(castDelegate);
        }
        private static Func <TFrom, TTo> GetCastDelegate <TFrom, TTo>()
        {
            object            del;
            Func <TFrom, TTo> castDelegate;

            if (!StrongCastLookup.TryGetInnerValue(typeof(TFrom), typeof(TTo), out del))
            {
                castDelegate = TypeExtensions.GetCastMethodDelegate <TFrom, TTo>();
                StrongCastLookup.AddInner(typeof(TFrom), typeof(TTo), castDelegate);
            }
            else
            {
                castDelegate = (Func <TFrom, TTo>)del;
            }

            return(castDelegate);
        }
Пример #3
0
        /// <summary>
        /// Gets an emitted formatter for a given type.
        /// <para />
        /// NOTE: Some platforms do not support emitting. On such platforms, this method logs an error and returns null. Check whether you can emit on the current platform using <see cref="EmitUtilities.CanEmit"/>.
        /// </summary>
        /// <param name="type">The type to emit a formatter for.</param>
        /// <param name="policy">The serialization policy to use to determine which members the emitted formatter should serialize. If null, <see cref="SerializationPolicies.Strict"/> is used.</param>
        /// <returns>The type of the emitted formatter.</returns>
        /// <exception cref="System.ArgumentNullException">The type argument is null.</exception>
        public static IFormatter GetEmittedFormatter(Type type, ISerializationPolicy policy)
        {
#if !CAN_EMIT
            Debug.LogError("Cannot use Reflection.Emit on the current platform. The FormatterEmitter class is currently disabled. Check whether emitting is currently possible with EmitUtilities.CanEmit.");
            return(null);
#else
            if (type == null)
            {
                throw new ArgumentNullException("type");
            }

            if (policy == null)
            {
                policy = SerializationPolicies.Strict;
            }

            IFormatter result = null;

            if (Formatters.TryGetInnerValue(policy, type, out result) == false)
            {
                lock (LOCK)
                {
                    if (Formatters.TryGetInnerValue(policy, type, out result) == false)
                    {
                        EnsureRuntimeAssembly();

                        try
                        {
                            result = CreateGenericFormatter(type, runtimeEmittedModule, policy);
                        }
                        catch (Exception ex)
                        {
                            Debug.LogError("The following error occurred while emitting a formatter for the type " + type.Name);
                            Debug.LogException(ex);
                        }

                        Formatters.AddInner(policy, type, result);
                    }
                }
            }

            return(result);
#endif
        }
        /// <summary>
        /// Creates an emitted MonoBehaviour-based <see cref="SerializedProperty"/>.
        /// </summary>
        /// <param name="fieldName">Name of the field to emit.</param>
        /// <param name="valueType">Type of the value to create a property for.</param>
        /// <param name="targetCount">The target count of the tree to create a property for.</param>
        /// <param name="gameObject">The game object that the MonoBehaviour of the property is located on.</param>
        /// <exception cref="System.ArgumentNullException">
        /// fieldName is null
        /// or
        /// valueType is null
        /// </exception>
        /// <exception cref="System.ArgumentException">Target count must be equal to or higher than 1.</exception>
        public static Handle CreateEmittedMonoBehaviourProperty(string fieldName, Type valueType, int targetCount, ref GameObject gameObject)
        {
            DestroyMarkedObjects();

            if (fieldName == null)
            {
                throw new ArgumentNullException("fieldName");
            }

            if (valueType == null)
            {
                throw new ArgumentNullException("valueType");
            }

            if (targetCount < 1)
            {
                throw new ArgumentException("Target count must be equal to or higher than 1.");
            }

            if (gameObject == null)
            {
                gameObject = HostGO;
            }

            Type resultType;

            if (!MonoBehaviourTypeCache.TryGetInnerValue(fieldName, valueType, out resultType))
            {
                resultType = EmitMonoBehaviourType(fieldName, valueType);
                MonoBehaviourTypeCache.AddInner(fieldName, valueType, resultType);
            }

            MonoBehaviour[] targets = new MonoBehaviour[targetCount];

            for (int i = 0; i < targetCount; i++)
            {
                targets[i]           = (MonoBehaviour)gameObject.AddComponent(resultType);
                targets[i].hideFlags = gameObject.hideFlags;
            }

            var serializedObject = new SerializedObject(targets);

            return(new Handle(serializedObject.FindProperty(fieldName), targets));
        }
        /// <summary>
        /// Creates an emitted ScriptableObject-based <see cref="SerializedProperty"/>.
        /// </summary>
        /// <param name="fieldName">Name of the field to emit.</param>
        /// <param name="valueType">Type of the value to create a property for.</param>
        /// <param name="targetCount">The target count of the tree to create a property for.</param>
        /// <exception cref="System.ArgumentNullException">
        /// fieldName is null
        /// or
        /// valueType is null
        /// </exception>
        /// <exception cref="System.ArgumentException">Target count must be equal to or higher than 1.</exception>
        public static SerializedProperty CreateEmittedScriptableObjectProperty(string fieldName, Type valueType, int targetCount)
        {
            DestroyMarkedObjects();

            if (fieldName == null)
            {
                throw new ArgumentNullException("fieldName");
            }

            if (valueType == null)
            {
                throw new ArgumentNullException("valueType");
            }

            if (targetCount < 1)
            {
                throw new ArgumentException("Target count must be equal to or higher than 1.");
            }

            Type resultType;

            if (PreCreatedScriptableObjectTypes.TryGetValue(valueType, out resultType))
            {
                fieldName = "value";
            }
            else if (!ScriptableObjectTypeCache.TryGetInnerValue(fieldName, valueType, out resultType))
            {
                resultType = EmitScriptableObjectType(fieldName, valueType);
                ScriptableObjectTypeCache.AddInner(fieldName, valueType, resultType);
            }

            ScriptableObject[] targets = new ScriptableObject[targetCount];

            for (int i = 0; i < targetCount; i++)
            {
                targets[i] = ScriptableObject.CreateInstance(resultType);
            }

            var serializedObject = new SerializedObject(targets);

            return(serializedObject.FindProperty(fieldName));
        }
Пример #6
0
        /// <summary>
        /// Gets a map of all serializable members on the given type. This will also properly map names extracted from <see cref="UnityEngine.Serialization.FormerlySerializedAsAttribute"/> and <see cref="PreviouslySerializedAsAttribute"/> to their corresponding members.
        /// </summary>
        /// <param name="type">The type to get a map for.</param>
        /// <param name="policy">The serialization policy to use. If null, <see cref="SerializationPolicies.Strict"/> is used.</param>
        /// <returns>A map of all serializable members on the given type.</returns>
        public static Dictionary <string, MemberInfo> GetSerializableMembersMap(Type type, ISerializationPolicy policy)
        {
            Dictionary <string, MemberInfo> result;

            if (policy == null)
            {
                policy = SerializationPolicies.Strict;
            }

            lock (LOCK)
            {
                if (MemberMapCache.TryGetInnerValue(policy, type, out result) == false)
                {
                    result = FindSerializableMembersMap(type, policy);
                    MemberMapCache.AddInner(policy, type, result);
                }
            }

            return(result);
        }
Пример #7
0
        /// <summary>
        /// Gets an array of all serializable members on the given type.
        /// </summary>
        /// <param name="type">The type to get serializable members for.</param>
        /// <param name="policy">The serialization policy to use. If null, <see cref="SerializationPolicies.Strict"/> is used.</param>
        /// <returns>An array of all serializable members on the given type.</returns>
        public static MemberInfo[] GetSerializableMembers(Type type, ISerializationPolicy policy)
        {
            MemberInfo[] result;

            if (policy == null)
            {
                policy = SerializationPolicies.Strict;
            }

            lock (LOCK)
            {
                if (MemberArrayCache.TryGetInnerValue(policy, type, out result) == false)
                {
                    List <MemberInfo> list = new List <MemberInfo>();
                    FindSerializableMembers(type, list, policy);
                    result = list.ToArray();
                    MemberArrayCache.AddInner(policy, type, result);
                }
            }

            return(result);
        }
Пример #8
0
        private static Func <MemberInfo, bool, IValueGetterSetter> GetEmittedGetterSetterCreator(Type ownerType, Type valueType)
        {
            Func <MemberInfo, bool, IValueGetterSetter> result;

            if (!GetterSetterCreators.TryGetInnerValue(ownerType, valueType, out result))
            {
                var type        = typeof(GetterSetter <,>).MakeGenericType(ownerType, valueType);
                var constructor = type.GetConstructor(GetterSetterConstructorSignature);

                var method = new DynamicMethod("GetterSetterCreator<" + ownerType.GetNiceName() + ", " + valueType.GetNiceName() + ">", typeof(IValueGetterSetter), new Type[] { typeof(MemberInfo), typeof(bool) });

                var il = method.GetILGenerator();

                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldarg_1);
                il.Emit(OpCodes.Newobj, constructor);
                il.Emit(OpCodes.Ret);

                result = (Func <MemberInfo, bool, IValueGetterSetter>)method.CreateDelegate(typeof(Func <MemberInfo, bool, IValueGetterSetter>));
                GetterSetterCreators.AddInner(ownerType, valueType, result);
            }

            return(result);
        }
Пример #9
0
        /// <summary>
        /// Gets a formatter for a given type.
        /// </summary>
        /// <param name="type">The type to get a formatter for.</param>
        /// <param name="policy">The serialization policy to use if a formatter has to be emitted. If null, <see cref="SerializationPolicies.Strict"/> is used.</param>
        /// <returns>
        /// A formatter for the given type.
        /// </returns>
        /// <exception cref="System.ArgumentNullException">The type argument is null.</exception>
        public static IFormatter GetFormatter(Type type, ISerializationPolicy policy)
        {
            if (type == null)
            {
                throw new ArgumentNullException("type");
            }

            if (policy == null)
            {
                policy = SerializationPolicies.Strict;
            }

            IFormatter result;

            lock (LOCK)
            {
                if (TypeFormatterMap.TryGetInnerValue(type, policy, out result) == false)
                {
                    // System.ExecutionEngineException is marked obsolete in .NET 4.6.
                    // That's all very good for .NET, but Unity still uses it, and that means we use it as well!
#pragma warning disable 618
                    try
                    {
                        result = CreateFormatter(type, policy);
                    }
                    catch (TargetInvocationException ex)
                    {
                        if (ex.GetBaseException() is ExecutionEngineException)
                        {
                            LogAOTError(type, ex.GetBaseException() as ExecutionEngineException);
                        }
                        else
                        {
                            throw ex;
                        }
                    }
                    catch (TypeInitializationException ex)
                    {
                        if (ex.GetBaseException() is ExecutionEngineException)
                        {
                            LogAOTError(type, ex.GetBaseException() as ExecutionEngineException);
                        }
                        else
                        {
                            throw ex;
                        }
                    }
                    catch (ExecutionEngineException ex)
                    {
                        LogAOTError(type, ex);
                    }

                    TypeFormatterMap.AddInner(type, policy, result);
#pragma warning restore 618
                }
            }

#if UNITY_EDITOR
            if (OnLocatedFormatter != null)
            {
                OnLocatedFormatter(result);
            }

            if (OnLocatedEmittableFormatterForType != null && result.GetType().IsGenericType)
            {
#if CAN_EMIT
                if (result.GetType().GetGenericTypeDefinition() == typeof(FormatterEmitter.RuntimeEmittedFormatter <>))
                {
                    OnLocatedEmittableFormatterForType(type);
                }
                else
#endif
                if (result.GetType().GetGenericTypeDefinition() == typeof(ReflectionFormatter <>))
                {
                    OnLocatedEmittableFormatterForType(type);
                }
            }
#endif

            return(result);
        }