コード例 #1
0
        private static ValueSetter CreateValueSetter(IValueEntry valueEntry)
        {
            var entryTypeInfo  = ValueEntryTypeInfo.Get(valueEntry.GetType());
            var entryType      = entryTypeInfo.Type;
            var entryValueType = entryTypeInfo.RootGenericArguments[1];
            var methodInfo     = entryType.GetMethod("SetValue", false, false, entryValueType, typeof(bool), typeof(bool));

            Assert.IsNotNull(methodInfo);

            var drawerValueType = typeof(TValue);

            Assert.IsTrue(entryValueType.IsAssignableFrom(drawerValueType));
            var parameterTypes = new[]
            { typeof(IValueEntry).MakeByRefType(), drawerValueType, typeof(bool), typeof(bool) };
            var dynamicMethod = new DynamicMethod(
                entryType.FullName + ".SetValue", typeof(ValueAccessResult), parameterTypes, entryType);

            /* Example Implementation:
             * static ValueAccessResult SetValue(ref IValueEntry valueEntry,
             *  Component value, bool handleErrorLogs, bool catchException)
             * {
             *  return ((FixedValueEntry<GameObject, Transform>)valueEntry)
             *      .SetValue((Transform)value, handleErrorLogs, catchException);
             * }
             */
            var gen = dynamicMethod.GetILGenerator();

            gen.Emit(OpCodes.Ldarg_0);                         // 0:entry
            gen.Emit(OpCodes.Ldind_Ref);
            gen.Emit(OpCodes.Castclass, entryType);            // 0:typedEntry
            gen.Emit(OpCodes.Ldarg_1);                         // 0:typedEntry 1:drawerTypeValue
            gen.EmitTypeCast(drawerValueType, entryValueType); // 0:typedEntry 1:entryValueType
            gen.Emit(OpCodes.Ldarg_2);                         // 0:typedEntry 1:entryTypeValue 2:handleErrorLogs
            gen.Emit(OpCodes.Ldarg_3);                         // 0:typedEntry 1:entryTypeValue 2:handleErrorLogs 3:catchException
            gen.Emit(OpCodes.Callvirt, methodInfo);            // 0:result
            gen.Emit(OpCodes.Ret);

            return((ValueSetter)dynamicMethod.CreateDelegate(typeof(ValueSetter)));
        }
コード例 #2
0
        private static ValueGetter CreateValueGetter(IValueEntry valueEntry)
        {
            var entryTypeInfo  = ValueEntryTypeInfo.Get(valueEntry.GetType());
            var entryType      = entryTypeInfo.Type;
            var entryValueType = entryTypeInfo.RootGenericArguments[1];
            var methodInfo     = entryType.GetMethod("GetValue", false, false,
                                                     entryValueType.MakeByRefType(), typeof(bool), typeof(bool));

            Assert.IsNotNull(methodInfo);

            // NOTE: This is a WRONG approach since valueType may different from TValue of current instance.
            //return (ValueGetter)Delegate.CreateDelegate(typeof(ValueGetter), method);

            var drawerValueType = typeof(TValue);

            Assert.IsTrue(entryValueType.IsAssignableFrom(drawerValueType));
            var parameterTypes = new[]
            { typeof(IValueEntry).MakeByRefType(), drawerValueType.MakeByRefType(), typeof(bool), typeof(bool) };
            var dynamicMethod = new DynamicMethod(
                entryType.FullName + ".GetValue", typeof(ValueAccessResult), parameterTypes, entryType);

            var gen = dynamicMethod.GetILGenerator();

            gen.Emit(OpCodes.Ldarg_0);              // 0:entry
            gen.Emit(OpCodes.Ldind_Ref);
            gen.Emit(OpCodes.Castclass, entryType); // 0:typedEntry
            if (drawerValueType == entryValueType)
            {
                /* Example Implementation:
                 * static ValueAccessResult ViewILGet(
                 *  ref IValueEntry valueEntry, out int value, bool handleErrorLogs, bool catchException)
                 * {
                 *  return ((FixedValueEntry<GameObject, int>)valueEntry)
                 *      .GetValue(out value, handleErrorLogs, catchException);
                 * }
                 */
                gen.Emit(OpCodes.Ldarg_1);
                gen.Emit(OpCodes.Ldarg_2);
                gen.Emit(OpCodes.Ldarg_3);
                gen.Emit(OpCodes.Callvirt, methodInfo); // 0:result
            }
            else
            {
                /* Example Implementation:
                 * static ValueAccessResult ViewILGet(ref IValueEntry valueEntry,
                 *  out Component value, bool handleErrorLogs, bool catchException)
                 * {
                 *  Transform entryValue;
                 *  var result = ((FixedValueEntry<GameObject, Transform>)valueEntry)
                 *      .GetValue(out entryValue, handleErrorLogs, catchException);
                 *  value = entryValue;
                 *  return result;
                 * }
                 */
                var valueInfo = gen.DeclareLocal(entryValueType);
                //var resultInfo = gen.DeclareLocal(typeof(ValueAccessResult));
                gen.Emit(OpCodes.Ldloca_S, valueInfo.LocalIndex); // 0:typedEntry 1:entryValue
                gen.Emit(OpCodes.Ldarg_2);                        // 0:typedEntry 1:entryValue 2:handleErrorLogs
                gen.Emit(OpCodes.Ldarg_3);                        // 0:typedEntry 1:entryValue 2:handleErrorLogs 3:catchException
                gen.Emit(OpCodes.Callvirt, methodInfo);           // 0:result
                gen.Emit(OpCodes.Ldarg_1);                        // 0:result 1:value
                gen.Emit(OpCodes.Ldloc, valueInfo.LocalIndex);    // 0:result 1:value 2:entryValue
                gen.Emit(OpCodes.Stind_Ref);                      // value = entryValue 0:result
            }
            gen.Emit(OpCodes.Ret);

            return((ValueGetter)dynamicMethod.CreateDelegate(typeof(ValueGetter)));
        }