コード例 #1
0
        /// <summary>
        /// Creates a dynamic detour method of the specified delegate type to wrap a base game
        /// method with the specified name. The dynamic method will automatically adapt if
        /// optional parameters are added, filling in their default values.
        /// </summary>
        /// <typeparam name="D">The delegate type to be used to call the detour.</typeparam>
        /// <param name="target">The target method to be called.</param>
        /// <returns>The detour that will call that method.</returns>
        /// <exception cref="DetourException">If the delegate does not match the target.</exception>
        public static D Detour <D>(this MethodInfo target) where D : Delegate
        {
            if (target == null)
            {
                throw new ArgumentNullException("target");
            }
            if (target.ContainsGenericParameters)
            {
                throw new ArgumentException("Generic types must have all parameters defined");
            }
            var expected           = DelegateInfo.Create(typeof(D));
            var parentType         = target.DeclaringType;
            var expectedParamTypes = expected.ParameterTypes;
            var actualParams       = ValidateDelegate(expected, target);
            int offset             = target.IsStatic ? 0 : 1;
            // Method will be "declared" in the type of the target, as we are detouring around
            // a method of that type
            var caller = new DynamicMethod(target.Name + "_Detour", expected.ReturnType,
                                           expectedParamTypes, parentType, true);
            var generator = caller.GetILGenerator();
            // Load the known method arguments onto the stack
            int n = expectedParamTypes.Length, need = actualParams.Length + offset;

            if (n > 0)
            {
                generator.Emit(OpCodes.Ldarg_0);
            }
            if (n > 1)
            {
                generator.Emit(OpCodes.Ldarg_1);
            }
            if (n > 2)
            {
                generator.Emit(OpCodes.Ldarg_2);
            }
            if (n > 3)
            {
                generator.Emit(OpCodes.Ldarg_3);
            }
            for (int i = 4; i < n; i++)
            {
                generator.Emit(OpCodes.Ldarg_S, i);
            }
            // Load the rest as defaults
            for (int i = n; i < need; i++)
            {
                var param = actualParams[i - offset];
                PTranspilerTools.GenerateDefaultLoad(generator, param.ParameterType, param.
                                                     DefaultValue);
            }
            if (parentType.IsValueType || target.IsStatic)
            {
                generator.Emit(OpCodes.Call, target);
            }
            else
            {
                generator.Emit(OpCodes.Callvirt, target);
            }
            generator.Emit(OpCodes.Ret);
            // Define the parameter names, parameter indexes start at 1
            if (offset > 0)
            {
                caller.DefineParameter(1, ParameterAttributes.None, "this");
            }
            for (int i = offset; i < n; i++)
            {
                var oldParam = actualParams[i - offset];
                caller.DefineParameter(i + 1, oldParam.Attributes, oldParam.Name);
            }
#if DEBUG
            PUtil.LogDebug("Created delegate {0} for method {1}.{2} with parameters [{3}]".
                           F(caller.Name, parentType.FullName, target.Name, actualParams.Join(",")));
#endif
            return(caller.CreateDelegate(typeof(D)) as D);
        }
コード例 #2
0
    public static void Main()
    {
        // Create an array that specifies the types of the parameters
        // of the dynamic method. This dynamic method has a String
        // parameter and an Integer parameter.
        Type[] helloArgs = { typeof(string), typeof(int) };

        // Create a dynamic method with the name "Hello", a return type
        // of Integer, and two parameters whose types are specified by
        // the array helloArgs. Create the method in the module that
        // defines the String class.
        DynamicMethod hello = new DynamicMethod("Hello",
                                                typeof(int),
                                                helloArgs,
                                                typeof(string).Module);

        // Create an array that specifies the parameter types of the
        // overload of Console.WriteLine to be used in Hello.
        Type[] writeStringArgs = { typeof(string) };
        // Get the overload of Console.WriteLine that has one
        // String parameter.
        MethodInfo writeString = typeof(Console).GetMethod("WriteLine",
                                                           writeStringArgs);

        // Get an ILGenerator and emit a body for the dynamic method,
        // using a stream size larger than the IL that will be
        // emitted.
        ILGenerator il = hello.GetILGenerator(256);

        // Load the first argument, which is a string, onto the stack.
        il.Emit(OpCodes.Ldarg_0);
        // Call the overload of Console.WriteLine that prints a string.
        il.EmitCall(OpCodes.Call, writeString, null);
        // The Hello method returns the value of the second argument;
        // to do this, load the onto the stack and return.
        il.Emit(OpCodes.Ldarg_1);
        il.Emit(OpCodes.Ret);

        // Add parameter information to the dynamic method. (This is not
        // necessary, but can be useful for debugging.) For each parameter,
        // identified by position, supply the parameter attributes and a
        // parameter name.
        hello.DefineParameter(1, ParameterAttributes.In, "message");
        hello.DefineParameter(2, ParameterAttributes.In, "valueToReturn");

        // Create a delegate that represents the dynamic method. This
        // action completes the method. Any further attempts to
        // change the method are ignored.
        HelloDelegate hi =
            (HelloDelegate)hello.CreateDelegate(typeof(HelloDelegate));

        // Use the delegate to execute the dynamic method.
        Console.WriteLine("\r\nUse the delegate to execute the dynamic method:");
        int retval = hi("\r\nHello, World!", 42);

        Console.WriteLine("Invoking delegate hi(\"Hello, World!\", 42) returned: " + retval);

        // Execute it again, with different arguments.
        retval = hi("\r\nHi, Mom!", 5280);
        Console.WriteLine("Invoking delegate hi(\"Hi, Mom!\", 5280) returned: " + retval);

        Console.WriteLine("\r\nUse the Invoke method to execute the dynamic method:");
        // Create an array of arguments to use with the Invoke method.
        object[] invokeArgs = { "\r\nHello, World!", 42 };
        // Invoke the dynamic method using the arguments. This is much
        // slower than using the delegate, because you must create an
        // array to contain the arguments, and value-type arguments
        // must be boxed.
        object objRet = hello.Invoke(null, BindingFlags.ExactBinding, null, invokeArgs, new CultureInfo("en-us"));

        Console.WriteLine("hello.Invoke returned: " + objRet);

        Console.WriteLine("\r\n ----- Display information about the dynamic method -----");
        // Display MethodAttributes for the dynamic method, set when
        // the dynamic method was created.
        Console.WriteLine("\r\nMethod Attributes: {0}", hello.Attributes);

        // Display the calling convention of the dynamic method, set when the
        // dynamic method was created.
        Console.WriteLine("\r\nCalling convention: {0}", hello.CallingConvention);

        // Display the declaring type, which is always null for dynamic
        // methods.
        if (hello.DeclaringType == null)
        {
            Console.WriteLine("\r\nDeclaringType is always null for dynamic methods.");
        }
        else
        {
            Console.WriteLine("DeclaringType: {0}", hello.DeclaringType);
        }

        // Display the default value for InitLocals.
        if (hello.InitLocals)
        {
            Console.Write("\r\nThis method contains verifiable code.");
        }
        else
        {
            Console.Write("\r\nThis method contains unverifiable code.");
        }
        Console.WriteLine(" (InitLocals = {0})", hello.InitLocals);

        // Display the module specified when the dynamic method was created.
        Console.WriteLine("\r\nModule: {0}", hello.Module);

        // Display the name specified when the dynamic method was created.
        // Note that the name can be blank.
        Console.WriteLine("\r\nName: {0}", hello.Name);

        // For dynamic methods, the reflected type is always null.
        if (hello.ReflectedType == null)
        {
            Console.WriteLine("\r\nReflectedType is null.");
        }
        else
        {
            Console.WriteLine("\r\nReflectedType: {0}", hello.ReflectedType);
        }

        if (hello.ReturnParameter == null)
        {
            Console.WriteLine("\r\nMethod has no return parameter.");
        }
        else
        {
            Console.WriteLine("\r\nReturn parameter: {0}", hello.ReturnParameter);
        }

        // If the method has no return type, ReturnType is System.Void.
        Console.WriteLine("\r\nReturn type: {0}", hello.ReturnType);

        // ReturnTypeCustomAttributes returns an ICustomeAttributeProvider
        // that can be used to enumerate the custom attributes of the
        // return value. At present, there is no way to set such custom
        // attributes, so the list is empty.
        if (hello.ReturnType == typeof(void))
        {
            Console.WriteLine("The method has no return type.");
        }
        else
        {
            ICustomAttributeProvider caProvider = hello.ReturnTypeCustomAttributes;
            object[] returnAttributes           = caProvider.GetCustomAttributes(true);
            if (returnAttributes.Length == 0)
            {
                Console.WriteLine("\r\nThe return type has no custom attributes.");
            }
            else
            {
                Console.WriteLine("\r\nThe return type has the following custom attributes:");
                foreach (object attr in returnAttributes)
                {
                    Console.WriteLine("\t{0}", attr.ToString());
                }
            }
        }

        Console.WriteLine("\r\nToString: {0}", hello.ToString());

        // Display parameter information.
        ParameterInfo[] parameters = hello.GetParameters();
        Console.WriteLine("\r\nParameters: name, type, ParameterAttributes");
        foreach (ParameterInfo p in parameters)
        {
            Console.WriteLine("\t{0}, {1}, {2}",
                              p.Name, p.ParameterType, p.Attributes);
        }
    }
コード例 #3
0
        private static void GenerateSerializeMethod()
        {
            object[] @namespace = new object[] { typeof(SerializeWriterHelper <Type, W>).Namespace, typeof(SerializeWriterHelper <Type, W>).Name, typeof(T).Namespace, typeof(T).Name };
            string   str        = string.Format("{0}.{1}.SerializeCore[{2}.{3}]", @namespace);

            Type[]        typeArray     = new Type[] { typeof(W).MakeByRefType(), typeof(T) };
            DynamicMethod dynamicMethod = new DynamicMethod(str, null, typeArray, typeof(SerializeWriterHelper <T, W>), true);

            dynamicMethod.DefineParameter(1, ParameterAttributes.In | ParameterAttributes.Out, "writer");
            dynamicMethod.DefineParameter(2, ParameterAttributes.In, "value");
            ILGenerator lGenerator = dynamicMethod.GetILGenerator();
            Type        baseType   = typeof(T);

            if (!baseType.IsSerializable && SerializeWriterHelper <T, W> .FindDefinedSerializeMethod(baseType) == null)
            {
                throw new SerializationException(string.Format("Type is not serializable: {0}", baseType.AssemblyQualifiedName));
            }
            Label?nullable = null;

            if (!baseType.IsValueType && SerializeWriterHelper <T, W> .FindDefinedSerializeMethod(baseType) == null)
            {
                MethodInfo method = SerializeWriterHelper <T, W> .FindDefinedSerializeMethod(typeof(bool));

                if (method == null)
                {
                    Type   type       = typeof(SerializeWriterHelper <,>);
                    Type[] typeArray1 = new Type[] { typeof(bool), typeof(W) };
                    method = type.MakeGenericType(typeArray1).GetMethod("Serialize");
                }
                lGenerator.Emit(OpCodes.Ldarg_0);
                lGenerator.Emit(OpCodes.Ldarg_1);
                lGenerator.Emit(OpCodes.Ldnull);
                lGenerator.Emit(OpCodes.Ceq);
                lGenerator.Emit(OpCodes.Ldc_I4_0);
                lGenerator.Emit(OpCodes.Ceq);
                lGenerator.EmitCall(OpCodes.Call, method, null);
                lGenerator.Emit(OpCodes.Ldarg_1);
                nullable = new Label?(lGenerator.DefineLabel());
                lGenerator.Emit(OpCodes.Brfalse, nullable.Value);
            }
            Stack <Type> types = new Stack <Type>();

            while (true)
            {
                if (baseType != null)
                {
                    MethodInfo methodInfo = SerializeWriterHelper <T, W> .FindDefinedSerializeMethod(baseType);

                    if (methodInfo == null)
                    {
                        if (baseType.IsSerializable)
                        {
                            types.Push(baseType);
                        }
                        baseType = baseType.BaseType;
                    }
                    else
                    {
                        SerializeWriterHelper <T, W> .EmitWritePredefinedType(lGenerator, methodInfo);

                        break;
                    }
                }
                else
                {
                    break;
                }
            }
            while (0 < types.Count)
            {
                SerializeWriterHelper <T, W> .EmitWriteFields(lGenerator, types.Pop());
            }
            if (nullable.HasValue)
            {
                lGenerator.MarkLabel(nullable.Value);
            }
            lGenerator.Emit(OpCodes.Ret);
            SerializeWriterHelper <T, W> .serializeCore = dynamicMethod.CreateDelegate(typeof(SerializeWriterHelper <T, W> .SerializeDelegate)) as SerializeWriterHelper <T, W> .SerializeDelegate;
            if (typeof(T).IsSealed || SerializeWriterHelper <T, W> .FindDefinedSerializeMethod(typeof(T)) != null)
            {
                SerializeWriterHelper <T, W> .serialize = SerializeWriterHelper <T, W> .serializeCore;
                return;
            }
            SerializeWriterHelper <T, W> .serialize = new SerializeWriterHelper <T, W> .SerializeDelegate(SerializeWriterHelper <T, W> .SerializeCoreVirtual);
        }
コード例 #4
0
        private static DynamicMethod CreateIl2CppShim(DynamicMethod patch, MethodBase original)
        {
            var patchName = patch.Name + "_il2cpp";

            var parameters     = patch.GetParameters();
            var result         = parameters.Types().ToList();
            var origParamTypes = result.ToArray();
            var paramTypes     = new Type[origParamTypes.Length];

            for (int i = 0; i < paramTypes.Length; ++i)
            {
                paramTypes[i] = Il2CppTypeForPatchType(origParamTypes[i]);
            }

            var origReturnType = AccessTools.GetReturnedType(patch);
            var returnType     = Il2CppTypeForPatchType(origReturnType);

            DynamicMethod method = new DynamicMethod(
                patchName,
                MethodAttributes.Public | MethodAttributes.Static,
                CallingConventions.Standard,
                returnType,
                paramTypes,
                original.DeclaringType,
                true
                );

            for (var i = 0; i < parameters.Length; i++)
            {
                method.DefineParameter(i + 1, parameters[i].Attributes, parameters[i].Name);
            }

            var il = method.GetILGenerator();

            LocalBuilder[] byRefValues = new LocalBuilder[parameters.Length];
            LocalBuilder   returnLocal = null;

            if (origReturnType != typeof(void))
            {
                returnLocal = il.DeclareLocal(origReturnType);
                Emitter.LogLocalVariable(il, returnLocal);
            }
            LocalBuilder exceptionLocal = il.DeclareLocal(typeof(Exception));

            Emitter.LogLocalVariable(il, exceptionLocal);

            // Start a try-block for the call to the original patch
            Emitter.MarkBlockBefore(il, new ExceptionBlock(ExceptionBlockType.BeginExceptionBlock, null), out _);

            // Load arguments, invoking the IntPrt -> Il2CppObject constructor for IL2CPP types
            for (int i = 0; i < origParamTypes.Length; ++i)
            {
                Emitter.Emit(il, OpCodes.Ldarg, i);
                ConvertArgument(il, origParamTypes[i], ref byRefValues[i]);
                if (byRefValues[i] != null)
                {
                    Emitter.LogLocalVariable(il, byRefValues[i]);
                }
            }

            // Call the original patch with the now-correct types
            Emitter.Emit(il, OpCodes.Call, patch);

            // Store the result, if any
            if (returnLocal != null)
            {
                Emitter.Emit(il, OpCodes.Stloc, returnLocal);
            }

            // Catch any exceptions that may have been thrown
            Emitter.MarkBlockBefore(il, new ExceptionBlock(ExceptionBlockType.BeginCatchBlock, typeof(Exception)), out _);

            // CumLogger.LogError("Exception in ...\n" + exception.ToString());
            Emitter.Emit(il, OpCodes.Stloc, exceptionLocal);
            Emitter.Emit(il, OpCodes.Ldstr, $"Exception in Harmony patch of method {original.FullDescription()}:\n");
            Emitter.Emit(il, OpCodes.Ldloc, exceptionLocal);
            Emitter.Emit(il, OpCodes.Call, AccessTools.DeclaredMethod(typeof(Exception), "ToString", new Type[0]));
            Emitter.Emit(il, OpCodes.Call, AccessTools.DeclaredMethod(typeof(string), "Concat", new Type[] { typeof(string), typeof(string) }));
            Emitter.Emit(il, OpCodes.Call, AccessTools.DeclaredMethod(typeof(CumLogger), "LogError", new Type[] { typeof(string) }));

            // Close the exception block
            Emitter.MarkBlockAfter(il, new ExceptionBlock(ExceptionBlockType.EndExceptionBlock, null));

            // Write back the pointers of ref arguments
            for (int i = 0; i < parameters.Length; ++i)
            {
                if (byRefValues[i] == null)
                {
                    continue;
                }

                Emitter.Emit(il, OpCodes.Ldarg, i);                 // -> [intptr*]
                Emitter.Emit(il, OpCodes.Ldloc, byRefValues[i]);    // -> [intptr*, obj]
                if (origParamTypes[i].GetElementType() == typeof(string))
                {
                    Emitter.Emit(il, OpCodes.Call, UnhollowerSupport.ManagedStringToIl2CppMethod);                     // -> [intptr*, intptr]
                }
                else
                {
                    Emitter.Emit(il, OpCodes.Call, UnhollowerSupport.Il2CppObjectBaseToPtrMethod); // -> [intptr*, intptr]
                }
                Emitter.Emit(il, OpCodes.Stind_I);                                                 // -> []
            }

            // Load the return value, if any, and unwrap it if required
            if (returnLocal != null)
            {
                Emitter.Emit(il, OpCodes.Ldloc, returnLocal);
                ConvertReturnValue(il, origReturnType);
            }

            Emitter.Emit(il, OpCodes.Ret);

            DynamicTools.PrepareDynamicMethod(method);
            return(method);
        }
コード例 #5
0
        public static void Generate(DynamicMethodDefinition dmd, MethodBase _mb, ILGenerator il)
        {
            MethodDefinition def = dmd.Definition;
            DynamicMethod    dm  = _mb as DynamicMethod;

#if !NETSTANDARD
            MethodBuilder mb            = _mb as MethodBuilder;
            ModuleBuilder moduleBuilder = mb?.Module as ModuleBuilder;
            // moduleBuilder.Assembly sometimes avoids the .Assembly override under mysterious circumstances.
            AssemblyBuilder    assemblyBuilder     = (mb?.DeclaringType as TypeBuilder)?.Assembly as AssemblyBuilder;
            HashSet <Assembly> accessChecksIgnored = null;
            if (mb != null)
            {
                accessChecksIgnored = new HashSet <Assembly>();
            }
#endif

#if !CECIL0_9
            MethodDebugInformation defInfo = dmd.Debug ? def.DebugInformation : null;
#endif

            if (dm != null)
            {
                foreach (ParameterDefinition param in def.Parameters)
                {
                    dm.DefineParameter(param.Index + 1, (System.Reflection.ParameterAttributes)param.Attributes, param.Name);
                }
            }
#if !NETSTANDARD
            if (mb != null)
            {
                foreach (ParameterDefinition param in def.Parameters)
                {
                    mb.DefineParameter(param.Index + 1, (System.Reflection.ParameterAttributes)param.Attributes, param.Name);
                }
            }
#endif

            LocalBuilder[] locals = def.Body.Variables.Select(
                var => {
                LocalBuilder local = il.DeclareLocal(var.VariableType.ResolveReflection(), var.IsPinned);
#if !NETSTANDARD && !CECIL0_9
                if (mb != null && defInfo != null && defInfo.TryGetName(var, out string name))
                {
                    local.SetLocalSymInfo(name);
                }
#endif
                return(local);
            }
                ).ToArray();

            // Pre-pass - Set up label map.
            Dictionary <Instruction, Label> labelMap = new Dictionary <Instruction, Label>();
            foreach (Instruction instr in def.Body.Instructions)
            {
                if (instr.Operand is Instruction[] targets)
                {
                    foreach (Instruction target in targets)
                    {
                        if (!labelMap.ContainsKey(target))
                        {
                            labelMap[target] = il.DefineLabel();
                        }
                    }
                }
                else if (instr.Operand is Instruction target)
                {
                    if (!labelMap.ContainsKey(target))
                    {
                        labelMap[target] = il.DefineLabel();
                    }
                }
            }

#if !NETSTANDARD && !CECIL0_9
            Dictionary <Document, ISymbolDocumentWriter> infoDocCache = mb == null ? null : new Dictionary <Document, ISymbolDocumentWriter>();
#endif

            int      paramOffs        = def.HasThis ? 1 : 0;
            object[] emitArgs         = new object[2];
            bool     checkTryEndEarly = false;
            foreach (Instruction instr in def.Body.Instructions)
            {
                if (labelMap.TryGetValue(instr, out Label label))
                {
                    il.MarkLabel(label);
                }

#if !NETSTANDARD && !CECIL0_9
                SequencePoint instrInfo = defInfo?.GetSequencePoint(instr);
                if (mb != null && instrInfo != null)
                {
                    if (!infoDocCache.TryGetValue(instrInfo.Document, out ISymbolDocumentWriter infoDoc))
                    {
                        infoDocCache[instrInfo.Document] = infoDoc = moduleBuilder.DefineDocument(
                            instrInfo.Document.Url,
                            instrInfo.Document.LanguageGuid,
                            instrInfo.Document.LanguageVendorGuid,
                            instrInfo.Document.TypeGuid
                            );
                    }
                    il.MarkSequencePoint(infoDoc, instrInfo.StartLine, instrInfo.StartColumn, instrInfo.EndLine, instrInfo.EndColumn);
                }
#endif

                foreach (ExceptionHandler handler in def.Body.ExceptionHandlers)
                {
                    if (checkTryEndEarly && handler.HandlerEnd == instr)
                    {
                        il.EndExceptionBlock();
                    }

                    if (handler.TryStart == instr)
                    {
                        il.BeginExceptionBlock();
                    }
                    else if (handler.FilterStart == instr)
                    {
                        il.BeginExceptFilterBlock();
                    }
                    else if (handler.HandlerStart == instr)
                    {
                        switch (handler.HandlerType)
                        {
                        case ExceptionHandlerType.Filter:
                            il.BeginCatchBlock(null);
                            break;

                        case ExceptionHandlerType.Catch:
                            il.BeginCatchBlock(handler.CatchType.ResolveReflection());
                            break;

                        case ExceptionHandlerType.Finally:
                            il.BeginFinallyBlock();
                            break;

                        case ExceptionHandlerType.Fault:
                            il.BeginFaultBlock();
                            break;
                        }
                    }

                    // Avoid duplicate endfilter / endfinally
                    if (handler.HandlerStart == instr.Next)
                    {
                        switch (handler.HandlerType)
                        {
                        case ExceptionHandlerType.Filter:
                            if (instr.OpCode == Mono.Cecil.Cil.OpCodes.Endfilter)
                            {
                                goto SkipEmit;
                            }
                            break;

                        case ExceptionHandlerType.Finally:
                            if (instr.OpCode == Mono.Cecil.Cil.OpCodes.Endfinally)
                            {
                                goto SkipEmit;
                            }
                            break;
                        }
                    }
                }

                if (instr.OpCode.OperandType == Mono.Cecil.Cil.OperandType.InlineNone)
                {
                    il.Emit(_ReflOpCodes[instr.OpCode.Value]);
                }
                else
                {
                    object operand = instr.Operand;

                    if (operand is Instruction[] targets)
                    {
                        operand = targets.Select(target => labelMap[target]).ToArray();
                        // Let's hope that the JIT treats the long forms identically to the short forms.
                        instr.OpCode = instr.OpCode.ToLongOp();
                    }
                    else if (operand is Instruction target)
                    {
                        operand = labelMap[target];
                        // Let's hope that the JIT treats the long forms identically to the short forms.
                        instr.OpCode = instr.OpCode.ToLongOp();
                    }
                    else if (operand is VariableDefinition var)
                    {
                        operand = locals[var.Index];
                    }
                    else if (operand is ParameterDefinition param)
                    {
                        operand = param.Index + paramOffs;
                    }
                    else if (operand is MemberReference mref)
                    {
                        if (mref is DynamicMethodReference dmref)
                        {
                            operand = dmref.DynamicMethod;
                        }
                        else
                        {
                            MemberInfo member = mref.ResolveReflection();
                            operand = member;
#if !NETSTANDARD
                            if (mb != null && member != null)
                            {
                                Assembly asm = member.Module.Assembly;
                                if (!accessChecksIgnored.Contains(asm))
                                {
                                    // while (member.DeclaringType != null)
                                    //     member = member.DeclaringType;
                                    assemblyBuilder.SetCustomAttribute(new CustomAttributeBuilder(DynamicMethodDefinition.c_IgnoresAccessChecksToAttribute, new object[] {
                                        asm.GetName().Name
                                    }));
                                    accessChecksIgnored.Add(asm);
                                }
                            }
#endif
                        }
                    }
                    else if (operand is CallSite csite)
                    {
                        if (dm != null)
                        {
                            // SignatureHelper in unmanaged contexts cannot be fully made use of for DynamicMethods.
                            _EmitCallSite(dm, il, _ReflOpCodes[instr.OpCode.Value], csite);
                            continue;
                        }
#if !NETSTANDARD
                        operand = csite.ResolveReflection(mb.Module);
#else
                        throw new NotSupportedException();
#endif
                    }

#if !NETSTANDARD
                    if (mb != null && operand is MethodBase called && called.DeclaringType == null)
                    {
                        // "Global" methods (f.e. DynamicMethods) cannot be tokenized.
                        if (instr.OpCode == Mono.Cecil.Cil.OpCodes.Call)
                        {
                            if (operand is DynamicMethod target)
                            {
                                // This should be heavily optimizable.
                                operand = _CreateMethodProxy(mb, target);
                            }
                            else
                            {
                                IntPtr ptr = called.GetLdftnPointer();
                                if (IntPtr.Size == 4)
                                {
                                    il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4, (int)ptr);
                                }
                                else
                                {
                                    il.Emit(System.Reflection.Emit.OpCodes.Ldc_I8, (long)ptr);
                                }
                                il.Emit(System.Reflection.Emit.OpCodes.Conv_I);
                                instr.OpCode = Mono.Cecil.Cil.OpCodes.Calli;
                                operand      = ((MethodReference)instr.Operand).ResolveReflectionSignature(mb.Module);
                            }
                        }
                        else
                        {
                            throw new NotSupportedException($"Unsupported global method operand on opcode {instr.OpCode.Name}");
                        }
                    }
#endif

                    if (operand == null)
                    {
                        throw new NullReferenceException($"Unexpected null in {def} @ {instr}");
                    }

                    il.DynEmit(_ReflOpCodes[instr.OpCode.Value], operand);
                }

                if (!checkTryEndEarly)
                {
                    foreach (ExceptionHandler handler in def.Body.ExceptionHandlers)
                    {
                        if (handler.HandlerEnd == instr.Next)
                        {
                            il.EndExceptionBlock();
                        }
                    }
                }

                checkTryEndEarly = false;
                continue;

SkipEmit:
                checkTryEndEarly = true;
                continue;
            }
        }
コード例 #6
0
        /// <summary>
        /// Define a method in this module with the specified name and parameters.
        /// </summary>
        public MethodInfo DefineMethod(string name, Type returnType, Type[] paramTypes, string[] paramNames, XmlILMethodAttributes xmlAttrs)
        {
            MethodInfo methResult;
            int        uniqueId = 1;
            string     nameOrig = name;

            Type[] paramTypesNew;
            bool   isRaw = (xmlAttrs & XmlILMethodAttributes.Raw) != 0;

            // Ensure that name is unique
            while (this.methods[name] != null)
            {
                // Add unique id to end of name in order to make it unique within this module
                uniqueId++;
                name = nameOrig + " (" + uniqueId + ")";
            }

            if (!isRaw)
            {
                // XmlQueryRuntime is always 0th parameter
                paramTypesNew    = new Type[paramTypes.Length + 1];
                paramTypesNew[0] = typeof(XmlQueryRuntime);
                Array.Copy(paramTypes, 0, paramTypesNew, 1, paramTypes.Length);
                paramTypes = paramTypesNew;
            }

            if (!this.useLRE)
            {
                MethodBuilder methBldr;

                methBldr = this.typeBldr.DefineMethod(
                    name,
                    MethodAttributes.Private | MethodAttributes.Static,
                    returnType,
                    paramTypes);

                if (emitSymbols && (xmlAttrs & XmlILMethodAttributes.NonUser) != 0)
                {
                    // Add DebuggerStepThroughAttribute and DebuggerNonUserCodeAttribute to non-user methods so that debugging is a better experience
                    methBldr.SetCustomAttribute(new CustomAttributeBuilder(XmlILConstructors.StepThrough, new object[] {}));
                    methBldr.SetCustomAttribute(new CustomAttributeBuilder(XmlILConstructors.NonUserCode, new object[] {}));
                }

                if (!isRaw)
                {
                    methBldr.DefineParameter(1, ParameterAttributes.None, RuntimeName);
                }

                for (int i = 0; i < paramNames.Length; i++)
                {
                    if (paramNames[i] != null && paramNames[i].Length != 0)
                    {
                        methBldr.DefineParameter(i + (isRaw ? 1 : 2), ParameterAttributes.None, paramNames[i]);
                    }
                }

                methResult = methBldr;
            }
            else
            {
                DynamicMethod methDyn = new DynamicMethod(name, returnType, paramTypes, LREModule);
                methDyn.InitLocals = true;

                if (!isRaw)
                {
                    methDyn.DefineParameter(1, ParameterAttributes.None, RuntimeName);
                }

                for (int i = 0; i < paramNames.Length; i++)
                {
                    if (paramNames[i] != null && paramNames[i].Length != 0)
                    {
                        methDyn.DefineParameter(i + (isRaw ? 1 : 2), ParameterAttributes.None, paramNames[i]);
                    }
                }

                methResult = methDyn;
            }

            // Index method by name
            this.methods[name] = methResult;
            return(methResult);
        }
コード例 #7
0
ファイル: SafeReflectionInvoker.cs プロジェクト: zsd4yr/wpf
        private static void CreateDynamicAssembly()
        {
            // 1. Assert permissions demanded by the DynamicMethod ctor.
            new SecurityPermission(SecurityPermissionFlag.ControlEvidence).Assert(); // BlessedAssert

            // 2. Create the transparent methods, each wrapping a call to a reflection method,
            //    and cache a delegate to each method.
            Type[]        parameterTypes;        // signature of the reflection method
            Type[]        wrappedParameterTypes; // signature of the wrapping method (when different)
            MethodInfo    mi;                    // descriptor for the reflection method
            DynamicMethod method;                // wrapping method
            ILGenerator   il;                    // wrapping method's generator

            // 2a. Delegate.CreateDelegate( Type, Type, String )
            parameterTypes = new Type[] { typeof(Type), typeof(Type), typeof(String) };
            mi             = typeof(Delegate).GetMethod("CreateDelegate", parameterTypes);

            method = new DynamicMethod("CreateDelegate", typeof(Delegate), parameterTypes);
            method.DefineParameter(1, ParameterAttributes.In, "delegateType");
            method.DefineParameter(2, ParameterAttributes.In, "targetType");
            method.DefineParameter(3, ParameterAttributes.In, "methodName");

            il = method.GetILGenerator(5);
            il.Emit(OpCodes.Ldarg_0);               // push delegateType
            il.Emit(OpCodes.Ldarg_1);               // push targetType
            il.Emit(OpCodes.Ldarg_2);               // push methodName
            il.EmitCall(OpCodes.Call, mi, null);    // call Delegate.CreateDelegate
            il.Emit(OpCodes.Ret);                   // return the result

            s_CreateDelegate1 = (CreateDelegate1Delegate)method.CreateDelegate(typeof(CreateDelegate1Delegate));

            // 2b. Delegate.CreateDelegate( Type, Object, String )
            parameterTypes = new Type[] { typeof(Type), typeof(Object), typeof(String) };
            mi             = typeof(Delegate).GetMethod("CreateDelegate", parameterTypes);

            method = new DynamicMethod("CreateDelegate", typeof(Delegate), parameterTypes);
            method.DefineParameter(1, ParameterAttributes.In, "delegateType");
            method.DefineParameter(2, ParameterAttributes.In, "target");
            method.DefineParameter(3, ParameterAttributes.In, "methodName");

            il = method.GetILGenerator(5);
            il.Emit(OpCodes.Ldarg_0);               // push delegateType
            il.Emit(OpCodes.Ldarg_1);               // push target
            il.Emit(OpCodes.Ldarg_2);               // push methodName
            il.EmitCall(OpCodes.Call, mi, null);    // call Delegate.CreateDelegate
            il.Emit(OpCodes.Ret);                   // return the result

            s_CreateDelegate2 = (CreateDelegate2Delegate)method.CreateDelegate(typeof(CreateDelegate2Delegate));

            // 2c. Activator.CreateInstance( Type, Object[] )
            parameterTypes = new Type[] { typeof(Type), typeof(Object[]) };
            mi             = typeof(Activator).GetMethod("CreateInstance", parameterTypes);

            method = new DynamicMethod("CreateInstance", typeof(Object), parameterTypes);
            method.DefineParameter(1, ParameterAttributes.In, "type");
            method.DefineParameter(2, ParameterAttributes.In, "arguments");

            il = method.GetILGenerator(4);
            il.Emit(OpCodes.Ldarg_0);               // push type
            il.Emit(OpCodes.Ldarg_1);               // push arguments
            il.EmitCall(OpCodes.Call, mi, null);    // call Activator.CreateInstance
            il.Emit(OpCodes.Ret);                   // return the result

            s_CreateInstance = (CreateInstanceDelegate)method.CreateDelegate(typeof(CreateInstanceDelegate));

            // 2d. MethodInfo.Invoke(object, args)
            parameterTypes        = new Type[] { typeof(Object), typeof(Object[]) };
            wrappedParameterTypes = new Type[] { typeof(MethodInfo), typeof(Object), typeof(Object[]) };
            mi = typeof(MethodInfo).GetMethod("Invoke", parameterTypes);

            method = new DynamicMethod("InvokeMethod", typeof(Object), wrappedParameterTypes);
            method.DefineParameter(1, ParameterAttributes.In, "method");
            method.DefineParameter(2, ParameterAttributes.In, "instance");
            method.DefineParameter(3, ParameterAttributes.In, "args");

            il = method.GetILGenerator(5);
            il.Emit(OpCodes.Ldarg_0);                // push method
            il.Emit(OpCodes.Ldarg_1);                // push instance
            il.Emit(OpCodes.Ldarg_2);                // push args
            il.EmitCall(OpCodes.Callvirt, mi, null); // call method.Invoke
            il.Emit(OpCodes.Ret);                    // return the result

            s_InvokeMethod = (InvokeMethodDelegate)method.CreateDelegate(typeof(InvokeMethodDelegate));
        }
コード例 #8
0
        /// <summary>
        /// Creates a dynamic method for testing units. All units take the same parameters.
        /// </summary>
        /// <param name="runner">The runner.</param>
        /// <returns></returns>
        public static DynamicUnitTiming CreateTestMethod(MethodRunner runner)
        {
            // Create the basic signature.
            var signature = new[] { typeof(object), typeof(int) };
            var method    = new DynamicMethod("DynamicUnitTest" + (counter++),
                                              typeof(void),
                                              signature,
                                              typeof(MethodRunnerCompiler));

            // Create an IL generator for the method body.
            ILGenerator il = method.GetILGenerator(256);

            // We determine what type of IL code we generate based on the singleton type.
            if (runner.TimingAttribute.Singleton)
            {
                // Create a single call version.
                CreateSingleton(runner, il);
            }
            else
            {
                // Create the local variables.
                il.DeclareLocal(typeof(int));
                il.DeclareLocal(typeof(bool));

                // Declare the labels.
                Label loopLabel = il.DefineLabel();
                Label topLabel  = il.DefineLabel();

                // Assign zero to the count variable.
                il.Emit(OpCodes.Ldc_I4_0);
                il.Emit(OpCodes.Stloc_0);
                il.Emit(OpCodes.Br_S, loopLabel);

                // Build up the actual execution.
                il.MarkLabel(topLabel);

                // Figure out how to call this method.
                il.Emit(OpCodes.Ldarg_0);

                switch (runner.MethodSignature)
                {
                case MethodSignature.CountInt32:
                    il.Emit(OpCodes.Ldloc_0);
                    break;

                case MethodSignature.CountIterationInt32:
                    il.Emit(OpCodes.Ldloc_0);
                    il.Emit(OpCodes.Ldarg_1);
                    break;
                }

                il.EmitCall(OpCodes.Call, runner.Method, null);

                // Increment the counter.
                il.Emit(OpCodes.Ldloc_0);
                il.Emit(OpCodes.Ldc_I4_1);
                il.Emit(OpCodes.Add);
                il.Emit(OpCodes.Stloc_0);

                // Create the loop test. This loads the count variable and compares
                // it to the second argument (iterations).
                il.MarkLabel(loopLabel);

                il.Emit(OpCodes.Ldloc_0);
                il.Emit(OpCodes.Ldarg_1);
                il.Emit(OpCodes.Clt);

                il.Emit(OpCodes.Stloc_1);
                il.Emit(OpCodes.Ldloc_1);
                il.Emit(OpCodes.Brtrue_S, topLabel);
            }

            // Finish up with a return IL.
            il.Emit(OpCodes.Ret);

            // Create the paramters.
            method.DefineParameter(0, ParameterAttributes.In, "target");
            method.DefineParameter(1, ParameterAttributes.In, "iteration");

            // Create the delegate and return it.
            return((DynamicUnitTiming)method.CreateDelegate(typeof(DynamicUnitTiming)));
        }
コード例 #9
0
        private static DynamicMethod CreateIl2CppShim(DynamicMethod original, Type owner)
        {
            var patchName = original.Name + "_il2cpp";

            var parameters     = original.GetParameters();
            var result         = parameters.Types().ToList();
            var origParamTypes = result.ToArray();
            var paramTypes     = new Type[origParamTypes.Length];

            for (int i = 0; i < paramTypes.Length; ++i)
            {
                paramTypes[i] = IsIl2CppType(origParamTypes[i]) ? typeof(IntPtr) : origParamTypes[i];
            }

            var origReturnType = AccessTools.GetReturnedType(original);
            var returnType     = IsIl2CppType(origReturnType) ? typeof(IntPtr) : origReturnType;

            DynamicMethod method;

            method = new DynamicMethod(
                patchName,
                MethodAttributes.Public | MethodAttributes.Static,
                CallingConventions.Standard,
                returnType,
                paramTypes,
                owner,
                true
                );

            for (var i = 0; i < parameters.Length; i++)
            {
                method.DefineParameter(i + 1, parameters[i].Attributes, parameters[i].Name);
            }

            var il = method.GetILGenerator();

            // Load arguments, invoking the IntPrt -> Il2CppObject constructor for IL2CPP types
            for (int i = 0; i < origParamTypes.Length; ++i)
            {
                Emitter.Emit(il, OpCodes.Ldarg, i);
                if (IsIl2CppType(origParamTypes[i]))
                {
                    Emitter.Emit(il, OpCodes.Newobj, Il2CppConstuctor(origParamTypes[i]));
                }
            }

            // Call the original patch with the now-correct types
            Emitter.Emit(il, OpCodes.Call, original);

            // If needed, unwrap the return value; then return
            if (IsIl2CppType(origReturnType))
            {
                var pointerGetter = AccessTools.DeclaredProperty(typeof(Il2CppObjectBase), "Pointer").GetMethod;
                Emitter.Emit(il, OpCodes.Call, pointerGetter);
            }

            Emitter.Emit(il, OpCodes.Ret);

            DynamicTools.PrepareDynamicMethod(method);
            return(method);
        }
コード例 #10
0
ファイル: Enigma.cs プロジェクト: xfixium/Rika
        private static Func <InputBitStream <ushort>, ushort> GetBitfieldReader(byte enabledFlags)
        {
            if (enabledFlags > 0x1f)
            {
                throw new ArgumentOutOfRangeException("enabledFlags");
            }

            // Lazily initialize the bitfield readers
            if (BitfieldReaders[enabledFlags] == null)
            {
                // Lock the array for thread safety
                lock (BitfieldReaders)
                {
                    // If the bitfield reader has been compiled while we were waiting for the lock, don't initialize it again!
                    if (BitfieldReaders[enabledFlags] == null)
                    {
                        DynamicMethod method = new DynamicMethod(
                            string.Format(CultureInfo.InvariantCulture, "ReadBitfield<{0}>", enabledFlags),
                            typeof(ushort),
                            new Type[] { typeof(InputBitStream <ushort>) });
                        method.DefineParameter(0, ParameterAttributes.None, "bitStream");
                        ILGenerator ilg = method.GetILGenerator();
                        if (enabledFlags == 0)
                        {
                            ilg.Emit(OpCodes.Ldc_I4_0);
                        }
                        else
                        {
                            // Keep track of how many bits are set, so we can generate the correct number of 'or' instructions
                            int bits = 0;

                            // Loop through the bits
                            for (int i = 4; i >= 0; i--)
                            {
                                // Test bits 4 to 0
                                if ((enabledFlags & (1 << i)) != 0)
                                {
                                    ++bits;

                                    // Call InputBitStream<ushort>.Get()
                                    ilg.Emit(OpCodes.Ldarg_0); // bitStream
                                    ilg.Emit(OpCodes.Callvirt, UShortInputBitStreamGet);

                                    // Shift the value by 15 to 11, depending on the bit being tested
                                    ilg.Emit(OpCodes.Ldc_I4_S, 11 + i);
                                    ilg.Emit(OpCodes.Shl);
                                }
                            }

                            // Decrement by one to keep one value on the stack
                            // For example, if enabledFlags is 0x1f, there will be 5 values on the stack. We want to end up with
                            // one value on the stack, so we must emit 4 'or' instructions.
                            --bits;
                            for (int i = 0; i < bits; i++)
                            {
                                // Emit 'or' instructions
                                ilg.Emit(OpCodes.Or);
                            }
                        }

                        ilg.Emit(OpCodes.Ret);

                        BitfieldReaders[enabledFlags] = (Func <InputBitStream <ushort>, ushort>)method.CreateDelegate(
                            typeof(Func <InputBitStream <ushort>, ushort>));
                    }
                }
            }

            return(BitfieldReaders[enabledFlags]);
        }
コード例 #11
0
        static Func <T, Action <PropertyChangedEventArgs>?> GetHandlerFinder()
        {
            var methods         = typeof(T).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
            var methodAndParams = methods
                                  .Where(x => (x.Name == "OnPropertyChanged" || x.Name == "RaisePropertyChanged") && x.ReturnType == typeof(void))
                                  .Select(method => (method, parameters: method.GetParameters()))
                                  .Where(x => x.parameters.Length == 1)
                                  .Select(x => (x.method, param: x.parameters[0]))
                                  .OrderBy(x => x.method.Name); // Grant priority for "OnPropertyChanged"

            foreach (var(method, param) in methodAndParams)
            {
                if (param.ParameterType == typeof(PropertyChangedEventArgs))
                {
                    // C#:
                    //   instance => instance.${method}
                    // IL:
                    //   ldarg.0
                    //   #if (is_virtual_method(${method}))
                    //     dup
                    //     ldvirtftn ${method}
                    //   #else
                    //     ldftn ${method}
                    //   newobj instance void Action<PropertyChangedEventArgs>::.ctor(object, native int)
                    //   ret
                    var dynamicMethod = new DynamicMethod("FindHandlerFromMethod", typeof(Action <PropertyChangedEventArgs>), new[] { typeof(T) }, true);
                    dynamicMethod.DefineParameter(1, ParameterAttributes.In, "instance");
                    var ilGenerator = dynamicMethod.GetILGenerator();
                    ilGenerator.Emit(OpCodes.Ldarg_0);
                    if (method.IsVirtual)
                    {
                        ilGenerator.Emit(OpCodes.Dup);
                        ilGenerator.Emit(OpCodes.Ldvirtftn, method);
                    }
                    else
                    {
                        ilGenerator.Emit(OpCodes.Ldftn, method);
                    }
                    ilGenerator.Emit(OpCodes.Newobj, typeof(Action <PropertyChangedEventArgs>).GetConstructor(new[] { typeof(object), typeof(IntPtr) }) !);
                    ilGenerator.Emit(OpCodes.Ret);
                    return((Func <T, Action <PropertyChangedEventArgs> >)dynamicMethod.CreateDelegate(typeof(Func <T, Action <PropertyChangedEventArgs> >)));
                }
                else if (param.ParameterType == typeof(string))
                {
                    // instance => e => instance.${method}(e.PropertyName);
                    var instance = Expression.Parameter(typeof(T));
                    var e        = Expression.Parameter(typeof(PropertyChangedEventArgs));
                    return(Expression.Lambda <Func <T, Action <PropertyChangedEventArgs> > >(
                               Expression.Lambda <Action <PropertyChangedEventArgs> >(
                                   Expression.Call(instance, method, Expression.PropertyOrField(e, nameof(PropertyChangedEventArgs.PropertyName))),
                                   e
                                   ),
                               instance
                               ).Compile());
                }
            }
            var field = typeof(T).GetField(nameof(INotifyPropertyChanged.PropertyChanged), BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

            if (field != null && field.FieldType == typeof(PropertyChangedEventHandler))
            {
                // instance => e => instance.${field}(instance, e);
                var instance = Expression.Parameter(typeof(T));
                var e        = Expression.Parameter(typeof(PropertyChangedEventArgs));
                return(Expression.Lambda <Func <T, Action <PropertyChangedEventArgs> > >(
                           Expression.Lambda <Action <PropertyChangedEventArgs> >(
                               Expression.Invoke(Expression.Field(instance, field), instance, e),
                               e
                               ),
                           instance
                           ).Compile());
            }
            return(_ => null);
        }
コード例 #12
0
        public static Formatter <T> GetFormatter <T>() where T : UdonSharpBehaviour
        {
            lock (_emitLock)
            {
                if (_formatters.TryGetValue(typeof(T), out IFormatter formatter))
                {
                    return((Formatter <T>)formatter);
                }

                List <FieldInfo> serializedFieldList    = new List <FieldInfo>();
                List <FieldInfo> nonSerializedFieldList = new List <FieldInfo>();

                Stack <Type> baseTypes = new Stack <Type>();

                Type currentType = typeof(T);

                while (currentType != null &&
                       currentType != typeof(UdonSharpBehaviour))
                {
                    baseTypes.Push(currentType);
                    currentType = currentType.BaseType;
                }

                List <FieldInfo> allFields = new List <FieldInfo>();

                while (baseTypes.Count > 0)
                {
                    currentType = baseTypes.Pop();
                    allFields.AddRange(currentType.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance));
                }

                foreach (FieldInfo field in allFields)
                {
                    // if (field.IsDefined(typeof(CompilerGeneratedAttribute), false))
                    //     continue;

                    if (FieldSymbol.IsFieldSerialized(field))
                    {
                        serializedFieldList.Add(field);
                    }
                    else
                    {
                        nonSerializedFieldList.Add(field);
                    }
                }

                FieldInfo[] publicFields  = serializedFieldList.ToArray();
                FieldInfo[] privateFields = nonSerializedFieldList.ToArray();

                EmittedFormatter <T> .Init(publicFields, privateFields);

                InitializeRuntimeAssemblyBuilder();

                BuildHelperType(typeof(T), publicFields, privateFields, out var serializerFields);

                Type     formatterType = typeof(EmittedFormatter <>).MakeGenericType(typeof(T));
                Delegate readDel, writeDel;

                // Read
                {
                    Type          readDelegateType = typeof(ReadDataMethodDelegate <>).MakeGenericType(typeof(T));
                    MethodInfo    readDataMethod   = formatterType.GetMethods(Flags.InstancePublic).First(e => e.Name == "Read" && e.GetParameters().Length == 2);
                    DynamicMethod readMethod       = new DynamicMethod($"Dynamic_{typeof(T).GetCompilableNiceFullName()}_Read", null, new[] { typeof(IValueStorage[]), typeof(T).MakeByRefType(), typeof(bool) }, true);

                    foreach (ParameterInfo param in readDataMethod.GetParameters())
                    {
                        readMethod.DefineParameter(param.Position, param.Attributes, param.Name);
                    }

                    EmitReadMethod(readMethod.GetILGenerator(), publicFields, privateFields, serializerFields);

                    readDel = readMethod.CreateDelegate(readDelegateType);
                }

                // Write
                {
                    Type          writeDelegateType = typeof(WriteDataMethodDelegate <>).MakeGenericType(typeof(T));
                    MethodInfo    writeDataMethod   = formatterType.GetMethods(Flags.InstancePublic).First(e => e.Name == "Write" && e.GetParameters().Length == 2);
                    DynamicMethod writeMethod       = new DynamicMethod($"Dynamic_{typeof(T).GetCompilableNiceFullName()}_Write", null, new[] { typeof(IValueStorage[]), typeof(T).MakeByRefType(), typeof(bool) }, true);

                    foreach (ParameterInfo param in writeDataMethod.GetParameters())
                    {
                        writeMethod.DefineParameter(param.Position, param.Attributes, param.Name);
                    }

                    EmitWriteMethod(writeMethod.GetILGenerator(), publicFields, privateFields, serializerFields);

                    writeDel = writeMethod.CreateDelegate(writeDelegateType);
                }

                formatter = (Formatter <T>)Activator.CreateInstance(typeof(EmittedFormatter <T>), readDel, writeDel);

                _formatters.Add(typeof(T), formatter);
                return((Formatter <T>)formatter);
            }
        }
コード例 #13
0
ファイル: DynamicMethodGen.cs プロジェクト: jmptrader/Creek
 protected override ParameterBuilder DefineParameter(int position, ParameterAttributes attributes, string parameterName)
 {
     return(dm.DefineParameter(position, attributes, parameterName));
 }
コード例 #14
0
        public static Formatter <T> GetFormatter <T>() where T : UdonSharpBehaviour
        {
            lock (emitLock)
            {
                IFormatter formatter;
                if (formatters.TryGetValue(typeof(T), out formatter))
                {
                    return((Formatter <T>)formatter);
                }

                List <FieldInfo> serializedFieldList    = new List <FieldInfo>();
                List <FieldInfo> nonSerializedFieldList = new List <FieldInfo>();

                FieldInfo[] allFields = typeof(T).GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);

                foreach (FieldInfo field in allFields)
                {
                    if ((field.IsPublic && field.GetAttribute <System.NonSerializedAttribute>() == null) ||
                        (!field.IsPublic && field.GetAttribute <SerializeField>() != null))
                    {
                        serializedFieldList.Add(field);
                    }
                    else
                    {
                        nonSerializedFieldList.Add(field);
                    }
                }

                FieldInfo[] publicFields  = serializedFieldList.ToArray();
                FieldInfo[] privateFields = nonSerializedFieldList.ToArray();

                EmittedFormatter <T> .Init(publicFields, privateFields);

                InitializeRuntimeAssemblyBuilder();

                Dictionary <System.Type, FieldBuilder> serializerFields;

                BuildHelperType(typeof(T), publicFields, privateFields, out serializerFields);

                System.Type     formatterType = typeof(EmittedFormatter <>).MakeGenericType(typeof(T));
                System.Delegate readDel, writeDel;

                // Read
                {
                    System.Type   readDelegateType = typeof(ReadDataMethodDelegate <>).MakeGenericType(typeof(T));
                    MethodInfo    readDataMethod   = formatterType.GetMethods(Flags.InstancePublic).Where(e => e.Name == "Read" && e.GetParameters().Length == 2).First();
                    DynamicMethod readMethod       = new DynamicMethod($"Dynamic_{typeof(T).GetCompilableNiceFullName()}_Read", null, new[] { typeof(IValueStorage[]), typeof(T).MakeByRefType(), typeof(bool) }, true);

                    foreach (ParameterInfo param in readDataMethod.GetParameters())
                    {
                        readMethod.DefineParameter(param.Position, param.Attributes, param.Name);
                    }

                    EmitReadMethod(readMethod.GetILGenerator(), typeof(T), publicFields, privateFields, serializerFields);

                    readDel = readMethod.CreateDelegate(readDelegateType);
                }

                // Write
                {
                    System.Type   writeDelegateType = typeof(WriteDataMethodDelegate <>).MakeGenericType(typeof(T));
                    MethodInfo    writeDataMethod   = formatterType.GetMethods(Flags.InstancePublic).Where(e => e.Name == "Write" && e.GetParameters().Length == 2).First();
                    DynamicMethod writeMethod       = new DynamicMethod($"Dynamic_{typeof(T).GetCompilableNiceFullName()}_Write", null, new[] { typeof(IValueStorage[]), typeof(T).MakeByRefType(), typeof(bool) }, true);

                    foreach (ParameterInfo param in writeDataMethod.GetParameters())
                    {
                        writeMethod.DefineParameter(param.Position, param.Attributes, param.Name);
                    }

                    EmitWriteMethod(writeMethod.GetILGenerator(), typeof(T), publicFields, privateFields, serializerFields);

                    writeDel = writeMethod.CreateDelegate(writeDelegateType);
                }

                formatter = (Formatter <T>)System.Activator.CreateInstance(typeof(EmittedFormatter <T>), readDel, writeDel);

                formatters.Add(typeof(T), formatter);
                return((Formatter <T>)formatter);
            }
        }
コード例 #15
0
        internal static DynamicMethod CreateDynamicMethod(MethodBase original, string suffix)
        {
            if (original == null)
            {
                throw new ArgumentNullException(nameof(original));
            }
            var patchName = original.Name + suffix;

            patchName = patchName.Replace("<>", "");

            var parameters     = original.GetParameters();
            var parameterTypes = parameters.Types().ToList();

            if (original.IsStatic == false)
            {
                if (AccessTools.IsStruct(original.DeclaringType))
                {
                    parameterTypes.Insert(0, original.DeclaringType.MakeByRefType());
                }
                else
                {
                    parameterTypes.Insert(0, original.DeclaringType);
                }
            }

            var firstArgIsReturnBuffer = NativeThisPointer.NeedsNativeThisPointerFix(original);

            if (firstArgIsReturnBuffer)
            {
                parameterTypes.Insert(0, typeof(IntPtr));
            }
            var returnType = firstArgIsReturnBuffer ? typeof(void) : AccessTools.GetReturnedType(original);

            // DynamicMethod does not support byref return types
            if (returnType == null || returnType.IsByRef)
            {
                return(null);
            }

            DynamicMethod method;

            try
            {
                method = new DynamicMethod(
                    patchName,
                    MethodAttributes.Public | MethodAttributes.Static,
                    CallingConventions.Standard,
                    returnType,
                    parameterTypes.ToArray(),
                    original.DeclaringType,
                    true
                    );
            }
            catch (Exception)
            {
                return(null);
            }

            var offset = (original.IsStatic ? 0 : 1) + (firstArgIsReturnBuffer ? 1 : 0);

            for (var i = 0; i < parameters.Length; i++)
            {
                method.DefineParameter(i + offset, parameters[i].Attributes, parameters[i].Name);
            }

            return(method);
        }
コード例 #16
0
ファイル: Program.cs プロジェクト: sbluen/sample
    public static void Main()
    {
        // Create an array that specifies the types of the parameters
        // of the dynamic method. This dynamic method has a String
        // parameter and an Integer parameter.
        Type[] helloArgs = {typeof(string), typeof(int), typeof(int)};

        // Create a dynamic method with the name "Hello", a return type
        // of Integer, and two parameters whose types are specified by
        // the array helloArgs. Create the method in the module that
        // defines the String class.
        DynamicMethod hello = new DynamicMethod("Hello",
            typeof(int),
            helloArgs,
            typeof(string).Module);

        // Create an array that specifies the parameter types of the
        // overload of Console.WriteLine to be used in Hello.
        Type[] writeStringArgs = {typeof(string)};
        // Get the overload of Console.WriteLine that has one
        // String parameter.
        MethodInfo writeString = typeof(Console).GetMethod("WriteLine",
            writeStringArgs);

        // Get an ILGenerator and emit a body for the dynamic method,
        // using a stream size larger than the IL that will be
        // emitted.
        ILGenerator il = hello.GetILGenerator(256);
        // Load the first argument, which is a string, onto the stack.
        il.Emit(OpCodes.Ldarg_0);
        // Call the overload of Console.WriteLine that prints a string.
        il.EmitCall(OpCodes.Call, writeString, null);
        // The Hello method returns the value of the second argument;
        // to do this, load the onto the stack and return.
        il.Emit(OpCodes.Ldarg_1);
        il.Emit(OpCodes.Ldc_I4_X, 1337);
        il.Emit(OpCodes.Add);
        il.Emit(OpCodes.Ret);

        // Add parameter information to the dynamic method. (This is not
        // necessary, but can be useful for debugging.) For each parameter,
        // identified by position, supply the parameter attributes and a
        // parameter name.
        hello.DefineParameter(1, ParameterAttributes.In, "message");
        hello.DefineParameter(2, ParameterAttributes.In, "valueToReturn");

        // Create a delegate that represents the dynamic method. This
        // action completes the method. Any further attempts to
        // change the method are ignored.
        HelloDelegate hi =
            (HelloDelegate) hello.CreateDelegate(typeof(HelloDelegate));

        // Use the delegate to execute the dynamic method.
        Console.WriteLine("\r\nUse the delegate to execute the dynamic method:");
        int retval = hi("\r\nHello, World!", 42, 30);
        Console.WriteLine("Invoking delegate hi(\"Hello, World!\", 42, 30) returned: " + retval);

        // Execute it again, with different arguments.
        retval = hi("\r\nHi, Mom!", 5280, 37);
        Console.WriteLine("Invoking delegate hi(\"Hi, Mom!\", 5280, 37) returned: " + retval);

        Console.WriteLine("\r\nUse the Invoke method to execute the dynamic method:");
        // Create an array of arguments to use with the Invoke method.
        object[] invokeArgs = {"\r\nHello, World!", 42, 30};
        // Invoke the dynamic method using the arguments. This is much
        // slower than using the delegate, because you must create an
        // array to contain the arguments, and value-type arguments
        // must be boxed.
        object objRet = hello.Invoke(null, BindingFlags.ExactBinding, null, invokeArgs, new CultureInfo("en-us"));
        Console.WriteLine("hello.Invoke returned: " + objRet);

        Console.WriteLine("\r\n ----- Display information about the dynamic method -----");
        // Display MethodAttributes for the dynamic method, set when
        // the dynamic method was created.
        Console.WriteLine("\r\nMethod Attributes: {0}", hello.Attributes);

        // Display the calling convention of the dynamic method, set when the
        // dynamic method was created.
        Console.WriteLine("\r\nCalling convention: {0}", hello.CallingConvention);

        // Display the declaring type, which is always null for dynamic
        // methods.
        if (hello.DeclaringType == null)
        {
            Console.WriteLine("\r\nDeclaringType is always null for dynamic methods.");
        }
        else
        {
            Console.WriteLine("DeclaringType: {0}", hello.DeclaringType);
        }

        // Display the default value for InitLocals.
        if (hello.InitLocals)
        {
            Console.Write("\r\nThis method contains verifiable code.");
        }
        else
        {
            Console.Write("\r\nThis method contains unverifiable code.");
        }
        Console.WriteLine(" (InitLocals = {0})", hello.InitLocals);

        // Display the module specified when the dynamic method was created.
        Console.WriteLine("\r\nModule: {0}", hello.Module);

        // Display the name specified when the dynamic method was created.
        // Note that the name can be blank.
        Console.WriteLine("\r\nName: {0}", hello.Name);

        // For dynamic methods, the reflected type is always null.
        if (hello.ReflectedType == null)
        {
            Console.WriteLine("\r\nReflectedType is null.");
        }
        else
        {
            Console.WriteLine("\r\nReflectedType: {0}", hello.ReflectedType);
        }

        //beyond scope of project
        //		if (hello.ReturnParameter == null)
        //		{
        //			Console.WriteLine("\r\nMethod has no return parameter.");
        //		}
        //		else
        //		{
        //			Console.WriteLine("\r\nReturn parameter: {0}", hello.ReturnParameter);
        //		}

        // If the method has no return type, ReturnType is System.Void.
        Console.WriteLine("\r\nReturn type: {0}", hello.ReturnType);

        // ReturnTypeCustomAttributes returns an ICustomeAttributeProvider
        // that can be used to enumerate the custom attributes of the
        // return value. At present, there is no way to set such custom
        // attributes, so the list is empty.
        //beyond scope of project
        //		if (hello.ReturnType == typeof(void))
        //		{
        //			Console.WriteLine("The method has no return type.");
        //		}
        //		else
        //		{
        //			ICustomAttributeProvider caProvider = hello.ReturnTypeCustomAttributes;
        //			object[] returnAttributes = caProvider.GetCustomAttributes(true);
        //			if (returnAttributes.Length == 0)
        //			{
        //				Console.WriteLine("\r\nThe return type has no custom attributes.");
        //			}
        //			else
        //			{
        //				Console.WriteLine("\r\nThe return type has the following custom attributes:");
        //				foreach( object attr in returnAttributes )
        //				{
        //					Console.WriteLine("\t{0}", attr.ToString());
        //				}
        //			}
        //		}

        Console.WriteLine("\r\nToString: {0}", hello.ToString());
        Console.WriteLine("\r\nToString: {0}", hello.ToString());

        // Display parameter information.
        ParameterInfo[] parameters = hello.GetParameters();
        Console.WriteLine("\r\nParameters: name, type, ParameterAttributes");
        foreach( ParameterInfo p in parameters )
        {
            Console.WriteLine("\t{0}, {1}, {2}",
                p.Name, p.ParameterType, p.Attributes);
        }
        Console.WriteLine("array assignment");
        Type[] paramTypes = { typeof(uint), typeof(string), typeof(string), typeof(uint) };
        Console.WriteLine(paramTypes[1]);
    }
コード例 #17
0
ファイル: DynamicDelegate.cs プロジェクト: liusj666/AxNew
        public static Delegate InstanceDelegate(Type dType, object target, FieldInfo funcField, MethodInfo methodAdapter)
        {
            MethodInfo dMethod = dType.GetMethod("Invoke");

            ParameterInfo[] dParemeters = dMethod.GetParameters();

            int len = dParemeters.Length;

            Type[] dParameterTypes = new Type[len + 1];
            dParameterTypes[0] = target.GetType();
            for (int i = 0; i < len; i++)
            {
                dParameterTypes[i + 1] = dParemeters[i].ParameterType;
            }


            DynamicMethod dynamicMethod = new DynamicMethod(
                Constant.FUNC_CON_INSTANCE_INVOKE,
                dMethod.ReturnType,
                dParameterTypes,
                target.GetType());

            ILGenerator il = dynamicMethod.GetILGenerator(256);

            il.DeclareLocal(typeof(object[]));      //object[] L0;
            il.DeclareLocal(typeof(object));        //object ret;
            il.DeclareLocal(dMethod.ReturnType);

            il.Emit(OpCodes.Ldc_I4, len);
            il.Emit(OpCodes.Newarr, typeof(object));
            il.Emit(OpCodes.Stloc, 0);

            for (int i = 0; i < len; i++)
            {
                il.Emit(OpCodes.Ldloc, 0);     //LOAD L0
                il.Emit(OpCodes.Ldc_I4, i);    //LOAD i
                il.Emit(OpCodes.Ldarg, i + 1); //LOAD arg[i+1]
                if (dParameterTypes[i].IsValueType)
                {
                    il.Emit(OpCodes.Box, dParameterTypes[i]);
                }
                il.Emit(OpCodes.Stelem_Ref);
            }

            il.Emit(OpCodes.Ldarg, 0);                      //LOAD target
            il.Emit(OpCodes.Ldfld, funcField);              //LOAD field
            il.Emit(OpCodes.Ldloc, 0);                      //LOAD L0
            il.EmitCall(OpCodes.Call, methodAdapter, null); //CallFunc(VAL, L0);
            il.Emit(OpCodes.Stloc, 1);
            il.Emit(OpCodes.Ldloc, 1);

            if (dMethod.ReturnType.IsValueType)
            {
                il.Emit(OpCodes.Unbox_Any, dMethod.ReturnType);
                il.Emit(OpCodes.Stloc, 2);
                il.Emit(OpCodes.Ldloc, 2);
            }

            il.Emit(OpCodes.Ret);

            for (int i = 0; i < len + 1; i++)
            {
                dynamicMethod.DefineParameter(i, ParameterAttributes.In, "arg" + i);
            }

            return(dynamicMethod.CreateDelegate(dType, target));
        }