예제 #1
0
        public static Func <Dictionary <string, object>, object> GenerateMethod(Type type)
        {
            var da = AppDomain.CurrentDomain.DefineDynamicAssembly(
                new AssemblyName("dyn"),                 // call it whatever you want
                AssemblyBuilderAccess.RunAndSave);

            var dm = da.DefineDynamicModule("dyn_mod", "dyn.dll");
            var dt = dm.DefineType("dyn_type");



            var emiter = Emit <Func <int> > .NewDynamicMethod("MyMethod");

            var method = dt.DefineMethod(
                "Foo",
                MethodAttributes.Public | MethodAttributes.Static, typeof(object),
                new[] { typeof(Dictionary <string, object>) });

            method.DefineParameter(1, ParameterAttributes.None, "dictionary");


            using (var il = new GroboIL(method))
            {
                var target = il.DeclareLocal(type);
                var value  = il.DeclareLocal(typeof(object));

                il.Newobj(type.GetConstructor(Type.EmptyTypes)); // [Person]
                il.Stloc(target);                                // []
                foreach (var property in type.GetProperties())
                {
                    var label = il.DefineLabel("ifLabel");

                    il.Ldarg(0);                          // [Dictionary<String, Object>]
                    il.Ldstr(property.Name);              // [Dictionary<String, Object>, String]
                    il.Ldloca(value);                     // [Dictionary<String, Object>, String, Object&]
                    il.Call(typeof(Dictionary <string, object>)
                            .GetMethod("TryGetValue"));   // [Boolean]

                    il.Brfalse(label);                    // []

                    il.Ldloc(target);                     // [Person]
                    il.Ldloc(value);                      // [Person, Object]
                    il.Castclass(typeof(string));         // [Dictionary<String, Object>, String]
                    il.Call(property.GetSetMethod(true)); // []

                    il.MarkLabel(label);
                }

                il.Ldloc(target);
                il.Ret();
                Console.WriteLine(il.GetILCode());
            }


            dt.CreateType();
            da.Save("dyn.dll");


            return((dic) => dt.GetMethod("Foo").Invoke(null, new object[] { dic }));
        }
예제 #2
0
 private void LoadTupleField(GroboIL il, ValueTupleField tupleFiled)
 {
     il.Ldstr(tupleFiled.NameInUserCode);
     il.Ldarga(0);
     il.Ldfld(tupleFiled.FieldInfo);
     if (tupleFiled.FieldInfo.FieldType.IsValueType)
     {
         il.Box(tupleFiled.FieldInfo.FieldType);
     }
 }
예제 #3
0
        private Func <string, string> BuildSwitch4()
        {
            Init(new[] { "0", "2", "5", "1000001", "7", "1000000" });
            var dynamicMethod = new DynamicMethod(Guid.NewGuid().ToString(), MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, typeof(string), new[] { typeof(string) }, Module, true);

            using (var il = new GroboIL(dynamicMethod))
            {
                var zzzLabel = il.DefineLabel("zzz");
                var qxxLabel = il.DefineLabel("qxx");
                var qzzLabel = il.DefineLabel("qzz");
                var xxxLabel = il.DefineLabel("xxx");
                var index    = il.DeclareLocal(typeof(uint));
                il.Ldfld(typeof(TestPerformance).GetField("testValues2"));
                il.Ldarg(0);
                il.Call(typeof(object).GetMethod("GetHashCode"), typeof(string));
                il.Ldc_I4(testValues2.Length);
                il.Rem(true);
                il.Stloc(index);
                il.Ldloc(index);
                il.Ldelem(typeof(string));
                il.Ldarg(0);
                il.Call(typeof(object).GetMethod("Equals", new[] { typeof(object) }), typeof(string));
                il.Brfalse(xxxLabel);
                il.Ldfld(typeof(TestPerformance).GetField("indexes2"));
                il.Ldloc(index);
                il.Ldelem(typeof(int));
                il.Switch(zzzLabel, zzzLabel, qxxLabel, qxxLabel, qzzLabel, qzzLabel);
                il.Br(xxxLabel);
                il.MarkLabel(zzzLabel);
                il.Ldstr("zzz");
                il.Ret();
                il.MarkLabel(qxxLabel);
                il.Ldstr("qxx");
                il.Ret();
                il.MarkLabel(qzzLabel);
                il.Ldstr("qzz");
                il.Ret();
                il.MarkLabel(xxxLabel);
                il.Ldstr("xxx");
                il.Ret();
            }
            return((Func <string, string>)dynamicMethod.CreateDelegate(typeof(Func <string, string>)));
        }
예제 #4
0
파일: Test.cs 프로젝트: qinfengzhu/gremit
        public void TestHelloWorld()
        {
            var method = new DynamicMethod(Guid.NewGuid().ToString(), typeof(string), Type.EmptyTypes, typeof(Test));

            using (var il = new GroboIL(method))
            {
                il.Ldstr("Hello World");
                il.Ret();
                Console.Write(il.GetILCode());
            }
        }
예제 #5
0
        private Func <int, string> BuildSwitch2()
        {
            var dynamicMethod = new DynamicMethod(Guid.NewGuid().ToString(), MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, typeof(string), new[] { typeof(int) }, Module, true);

            using (var il = new GroboIL(dynamicMethod))
            {
                var zzzLabel = il.DefineLabel("zzz");
                var qxxLabel = il.DefineLabel("qxx");
                var qzzLabel = il.DefineLabel("qzz");
                var xxxLabel = il.DefineLabel("xxx");
                var index    = il.DeclareLocal(typeof(uint));
                il.Ldfld(typeof(TestPerformance).GetField("testValues"));
                il.Ldarg(0);
                il.Ldc_I4(14);
                il.Rem(true);
                il.Stloc(index);
                il.Ldloc(index);
                il.Ldelem(typeof(int));
                il.Ldarg(0);
                il.Bne_Un(xxxLabel);
                il.Ldfld(typeof(TestPerformance).GetField("indexes"));
                il.Ldloc(index);
                il.Ldelem(typeof(int));
                il.Switch(zzzLabel, zzzLabel, qxxLabel, qzzLabel, qzzLabel, qxxLabel);
                il.Br(xxxLabel);
                il.MarkLabel(zzzLabel);
                il.Ldstr("zzz");
                il.Ret();
                il.MarkLabel(qxxLabel);
                il.Ldstr("qxx");
                il.Ret();
                il.MarkLabel(qzzLabel);
                il.Ldstr("qzz");
                il.Ret();
                il.MarkLabel(xxxLabel);
                il.Ldstr("xxx");
                il.Ret();
            }
            return((Func <int, string>)dynamicMethod.CreateDelegate(typeof(Func <int, string>)));
        }
예제 #6
0
        private static void EmitCrashIfValueIsNull(GroboIL il)
        {
            var box = il.DefineLabel("box");

            il.Dup();
            il.Brtrue(box);
            var crashConstructor = typeof(ArgumentException).GetConstructor(new[] { typeof(string) });

            il.Ldstr("bad parameter");
            il.Newobj(crashConstructor);
            il.Throw();
            il.MarkLabel(box);
        }
예제 #7
0
        private Func <int, string> BuildSwitch1()
        {
            var dynamicMethod = new DynamicMethod(Guid.NewGuid().ToString(), MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, typeof(string), new[] { typeof(int) }, Module, true);

            using (var il = new GroboIL(dynamicMethod))
            {
                il.Ldarg(0);
                var zzzLabel = il.DefineLabel("zzz");
                var qxxLabel = il.DefineLabel("qxx");
                var qzzLabel = il.DefineLabel("qzz");
                var xxxLabel = il.DefineLabel("xxx");
                il.Switch(zzzLabel, xxxLabel, zzzLabel);
                il.Ldarg(0);
                il.Ldc_I4(5);
                il.Sub();
                il.Switch(qxxLabel, xxxLabel, qzzLabel);
                il.Ldarg(0);
                il.Ldc_I4(0xf4240);
                il.Sub();
                il.Switch(qzzLabel, qxxLabel);
                il.Br(xxxLabel);
                il.MarkLabel(zzzLabel);
                il.Ldstr("zzz");
                il.Ret();
                il.MarkLabel(qxxLabel);
                il.Ldstr("qxx");
                il.Ret();
                il.MarkLabel(qzzLabel);
                il.Ldstr("qzz");
                il.Ret();
                il.MarkLabel(xxxLabel);
                il.Ldstr("xxx");
                il.Ret();
            }
            return((Func <int, string>)dynamicMethod.CreateDelegate(typeof(Func <int, string>)));
        }
예제 #8
0
파일: Test.cs 프로젝트: qinfengzhu/gremit
        private IQxx BuildIfs(ModuleBuilder module, string[] keys)
        {
            var numberOfCases = keys.Length;
            var typeBuilder   = module.DefineType("Ifs" + Guid.NewGuid(), TypeAttributes.Class | TypeAttributes.Public);

            typeBuilder.AddInterfaceImplementation(typeof(IQxx));
            var fields = new FieldInfo[numberOfCases];

            for (var i = 0; i < numberOfCases; ++i)
            {
                fields[i] = typeBuilder.DefineField(keys[i], typeof(int), FieldAttributes.Public);
            }
            var method = typeBuilder.DefineMethod("Set", MethodAttributes.Public | MethodAttributes.Virtual, typeof(void), new[] { typeof(string), typeof(int) });

            method.DefineParameter(1, ParameterAttributes.In, "key");
            method.DefineParameter(2, ParameterAttributes.In, "value");
            using (var il = new GroboIL(method))
            {
                var doneLabel = il.DefineLabel("done");
                for (var i = 0; i < numberOfCases; ++i)
                {
                    il.Ldarg(1);                     // stack: [key]
                    il.Ldstr(keys[i]);               // stack: [key, keys[i]]
                    il.Call(stringEqualityOperator); // stack: [key == keys[i]]
                    var nextKeyLabel = il.DefineLabel("nextKey");
                    il.Brfalse(nextKeyLabel);        // if(key != keys[i]) goto nextKey; stack: []
                    il.Ldarg(0);
                    il.Ldarg(2);
                    il.Stfld(fields[i]);
                    il.Br(doneLabel);
                    il.MarkLabel(nextKeyLabel);
                }
                il.MarkLabel(doneLabel);
                il.Ret();
            }
            typeBuilder.DefineMethodOverride(method, typeof(IQxx).GetMethod("Set"));
            var type = typeBuilder.CreateType();

            return((IQxx)Activator.CreateInstance(type));
        }
예제 #9
0
파일: Test.cs 프로젝트: qinfengzhu/gremit
        public void TestFarsh()
        {
            var method = new DynamicMethod(Guid.NewGuid().ToString(), typeof(int), new[] { typeof(int) }, typeof(Test));

            using (var il = new GroboIL(method))
            {
                var temp = il.DeclareLocal(typeof(int));
                il.Ldarg(0);   // stack: [x]
                var label0 = il.DefineLabel("L");
                il.Br(label0); // goto L_0; stack: [x]

                il.Ldstr("zzz");
                il.Ldobj(typeof(DateTime));
                il.Mul();
                il.Initobj(typeof(int));

                var label1 = il.DefineLabel("L");
                il.MarkLabel(label1);  // stack: [x, 2]
                il.Stloc(temp);        // temp = 2; stack: [x]
                var label2 = il.DefineLabel("L");
                il.MarkLabel(label2);  // stack: [cur]
                il.Ldarg(0);           // stack: [cur, x]
                il.Mul();              // stack: [cur * x = cur]
                il.Ldloc(temp);        // stack: [cur, temp]
                il.Ldc_I4(1);          // stack: [cur, temp, 1]
                il.Sub();              // stack: [cur, temp - 1]
                il.Stloc(temp);        // temp = temp - 1; stack: [cur]
                il.Ldloc(temp);        // stack: [cur, temp]
                il.Ldc_I4(0);          // stack: [cur, temp, 0]
                il.Bgt(label2, false); // if(temp > 0) goto L_2; stack: [cur]
                var label3 = il.DefineLabel("L");
                il.Br(label3);         // goto L_3; stack: [cur]
                il.MarkLabel(label0);  // stack: [x]
                il.Ldc_I4(2);          // stack: [x, 2]
                il.Br(label1);         // goto L_1; stack: [x, 2]
                il.MarkLabel(label3);  // stack: [cur]
                il.Ret();              // return cur; stack: []
                Console.Write(il.GetILCode());
            }
        }
예제 #10
0
        public static TryGetValueDelegate <T> Build <T>(string[] keys, T[] values)
        {
            var method = new DynamicMethod(Guid.NewGuid().ToString(), typeof(bool),
                                           new[] { typeof(T[]), typeof(string), typeof(T).MakeByRefType() }, typeof(string), true);

            using (var il = new GroboIL(method))
            {
                for (int i = 0; i < keys.Length; ++i)
                {
                    il.Ldarg(1);                     // stack: [key]
                    il.Ldstr(keys[i]);               // stack: [key, keys[i]]
                    var nextKeyLabel = il.DefineLabel("nextKey");
                    il.Call(stringEqualityOperator); // stack: [key == keys[i]]
                    il.Brfalse(nextKeyLabel);        // if(key != keys[i]) goto nextKey; stack: []
                    il.Ldarg(2);                     // stack: [ref value]
                    il.Ldarg(0);                     // stack: [ref value, values]
                    il.Ldc_I4(i);                    // stack: [ref value, values, i]
                    il.Ldelem(typeof(T));            // stack: [ref value, values[i]]
                    il.Stind(typeof(T));             // value = values[i]; stack: []
                    il.Ldc_I4(1);                    // stack: [true]
                    il.Ret();
                    il.MarkLabel(nextKeyLabel);
                }
                il.Ldarg(2); // stack: [ref value]
                if (typeof(T).IsValueType)
                {
                    il.Initobj(typeof(T)); // value = default(T); stack: []
                }
                else
                {
                    il.Ldnull();         // stack: [ref value, null]
                    il.Stind(typeof(T)); // value = null; stack: []
                }
                il.Ldc_I4(0);            // stack: [false]
                il.Ret();
            }
            return((TryGetValueDelegate <T>)method.CreateDelegate(typeof(TryGetValueDelegate <T>), values));
        }
예제 #11
0
        private static void DefineMethodOverrideWithInterception(TypeBuilder typeBuilder, MethodBuilder methodBuilder, MethodInfo overridedMethod, Dictionary <Type, FieldInfo> interceptorFields, MethodInfo genericInterceptionAction, MethodInfo voidInterceptionAction, FieldBuilder concreteInstance, ParameterInfo[] methodParams, Type[] genericParameterTypes, Type[] interceptors)
        {
            var @delegate = GenerateOverloadedMethodDelegate(overridedMethod, typeBuilder, concreteInstance);

            for (var i = 0; i < interceptors.Length; i++)
            {
                var interceptor = interceptors[i];

                @delegate = DefineMethodInterceptingDelegate(typeBuilder, overridedMethod, interceptorFields, genericInterceptionAction, voidInterceptionAction, genericParameterTypes, @delegate, i, interceptor);
            }

            using (var il = new GroboIL(methodBuilder))
            {
                var paramInfoType  = typeof(ParamInfo);
                var paramsInfoType = typeof(ParamInfo[]);
                var paramsInfo     = il.DeclareLocal(paramsInfoType);
                var paramInfo      = il.DeclareLocal(paramInfoType);

                il.Nop();

                il.Ldc_I4(methodParams.Length);
                il.Newarr(typeof(ParamInfo));
                il.Stloc(paramsInfo);

                var paramInfoConstructor = paramInfoType.GetConstructor(new[] { typeof(string), typeof(Type), typeof(bool), typeof(bool) });
                var paramInfoValueSetter = paramInfoType.GetProperty("Value").GetSetMethod();
                var getTypeMethod        = typeof(Type).GetMethod("GetTypeFromHandle", new[] { typeof(RuntimeTypeHandle) });

                var idx = 0;
                foreach (var parameter in methodParams)
                {
                    // load array at index
                    il.Ldloc(paramsInfo);
                    il.Ldc_I4(idx++);

                    // Load ParamInfo.Name
                    il.Ldstr(parameter.Name);

                    // Load ParamInfo.Type
                    if (parameter.IsOut || parameter.ParameterType.IsByRef)
                    {
                        il.Ldtoken(parameter.ParameterType.GetElementType());
                    }
                    else
                    {
                        il.Ldtoken(parameter.ParameterType);
                    }

                    il.Call(getTypeMethod);

                    // Load ParamInfo.IsByRef
                    if (parameter.ParameterType.IsByRef)
                    {
                        il.Ldc_I4(1);
                    }
                    else
                    {
                        il.Ldc_I4(0);
                    }

                    // Load ParamInfo.IsOut
                    if (parameter.IsOut)
                    {
                        il.Ldc_I4(1);
                    }
                    else
                    {
                        il.Ldc_I4(0);
                    }

                    // instantiate ParamInfo
                    il.Newobj(paramInfoConstructor);
                    il.Stloc(paramInfo);

                    // Set ParamInfo.Value
                    il.Ldloc(paramInfo);
                    il.Ldarg(parameter.Position + 1);
                    if (parameter.IsOut || parameter.ParameterType.IsByRef)
                    {
                        il.Ldobj(parameter.ParameterType.GetElementType());

                        if (parameter.ParameterType.GetElementType().IsValueType || parameter.ParameterType.GetElementType().IsGenericParameter)
                        {
                            il.Box(parameter.ParameterType.GetElementType());
                        }
                    }
                    else
                    {
                        if (parameter.ParameterType.IsValueType || parameter.ParameterType.IsGenericParameter)
                        {
                            il.Box(parameter.ParameterType);
                        }
                    }

                    il.Call(paramInfoValueSetter);
                    il.Nop();

                    // push to array
                    il.Ldloc(paramInfo);
                    il.Stelem(paramInfoType);
                }

                il.Ldarg(0);
                il.Ldloc(paramsInfo);
                if (overridedMethod.IsGenericMethodDefinition)
                {
                    il.Call(@delegate.MakeGenericMethod(genericParameterTypes));
                }
                else
                {
                    il.Call(@delegate);
                }

                idx = 1;
                var paramInfoValueGetter = paramInfoType.GetProperty("Value").GetGetMethod();
                foreach (var parameter in methodParams)
                {
                    if (parameter.IsOut || parameter.ParameterType.IsByRef)
                    {
                        il.Ldarg(idx);
                        il.Ldloc(paramsInfo);
                        il.Ldc_I4(idx - 1);
                        il.Ldelem(paramInfoType);
                        il.Call(paramInfoValueGetter);

                        if (parameter.ParameterType.GetElementType().IsValueType)
                        {
                            il.Unbox_Any(parameter.ParameterType.GetElementType());
                        }

                        il.Stobj(parameter.ParameterType.GetElementType());
                    }

                    idx++;
                }

                il.Ret();

                LogIlCode(il);
            }
        }
예제 #12
0
        public void Test1()
        {
            var overflow    = typeof(OverflowException);
            var exCtorInfo  = overflow.GetConstructor(new[] { typeof(string) });
            var exToStrMI   = overflow.GetMethod("ToString");
            var writeLineMI = typeof(Console).GetMethod("WriteLine",
                                                        new[]
            {
                typeof(string),
                typeof(object)
            });

            var method = new DynamicMethod(Guid.NewGuid().ToString(), typeof(int), new[] { typeof(int), typeof(int) }, typeof(TestTryCatch));

            using (var il = new GroboIL(method))
            {
                GroboIL.Local tmp1 = il.DeclareLocal(typeof(int));
                GroboIL.Local tmp2 = il.DeclareLocal(overflow);

                // In order to successfully branch, we need to create labels
                // representing the offset IL instruction block to branch to.
                // These labels, when the MarkLabel(Label) method is invoked,
                // will specify the IL instruction to branch to.
                //
                GroboIL.Label failed    = il.DefineLabel("failed");
                GroboIL.Label endOfMthd = il.DefineLabel("end");

                // Begin the try block.
                il.BeginExceptionBlock();

                // First, load argument 0 and the integer value of "100" onto the
                // stack. If arg0 > 100, branch to the label "failed", which is marked
                // as the address of the block that throws an exception.
                //
                il.Ldarg(0);
                il.Ldc_I4(100);
                il.Bgt(failed, false);

                // Now, check to see if argument 1 was greater than 100. If it was,
                // branch to "failed." Otherwise, fall through and perform the addition,
                // branching unconditionally to the instruction at the label "endOfMthd".
                //
                il.Ldarg(1);
                il.Ldc_I4(100);
                il.Bgt(failed, false);

                il.Ldarg(0);
                il.Ldarg(1);
                il.Add_Ovf(true);
                // Store the result of the addition.
                il.Stloc(tmp1);
                il.Leave(endOfMthd);

                // If one of the arguments was greater than 100, we need to throw an
                // exception. We'll use "OverflowException" with a customized message.
                // First, we load our message onto the stack, and then create a new
                // exception object using the constructor overload that accepts a
                // string message.
                //
                il.MarkLabel(failed);
                il.Ldstr("Cannot accept values over 100 for add.");
                il.Newobj(exCtorInfo);

                // We're going to need to refer to that exception object later, so let's
                // store it in a temporary variable. Since the store function pops the
                // the value/reference off the stack, and we'll need it to throw the
                // exception, we will subsequently load it back onto the stack as well.

                il.Stloc(tmp2);
                il.Ldloc(tmp2);

                // Throw the exception now on the stack.

                il.Throw();

                // Start the catch block for OverflowException.
                //
                il.BeginCatchBlock(overflow);

                // When we enter the catch block, the thrown exception
                // is on the stack. Store it, then load the format string
                // for WriteLine.
                //
                il.Stloc(tmp2);
                il.Ldstr("Caught {0}");

                // Push the thrown exception back on the stack, then
                // call its ToString() method. Note that if this catch block
                // were for a more general exception type, like Exception,
                // it would be necessary to use the ToString for that type.
                //
                il.Ldloc(tmp2);
                il.Call(exToStrMI);

                // The format string and the return value from ToString() are
                // now on the stack. Call WriteLine(string, object).
                //
                il.Call(writeLineMI);

                // Since our function has to return an integer value, we'll load -1 onto
                // the stack to indicate an error, and store it in local variable tmp1.
                //
                il.Ldc_I4(-1);
                il.Stloc(tmp1);

                // End the exception handling block.

                il.EndExceptionBlock();

                // The end of the method. If no exception was thrown, the correct value
                // will be saved in tmp1. If an exception was thrown, tmp1 will be equal
                // to -1. Either way, we'll load the value of tmp1 onto the stack and return.
                //
                il.MarkLabel(endOfMthd);
                il.Ldloc(tmp1);
                il.Ret();

                Console.WriteLine(il.GetILCode());
            }
        }
예제 #13
0
        public void Test2()
        {
            AssemblyName myAssemblyName = new AssemblyName();

            myAssemblyName.Name = "AdderExceptionAsm";

            // Create dynamic assembly.
            AppDomain       myAppDomain       = Thread.GetDomain();
            AssemblyBuilder myAssemblyBuilder = myAppDomain.DefineDynamicAssembly(myAssemblyName, AssemblyBuilderAccess.RunAndSave);

            // Create a dynamic module.
            ModuleBuilder myModuleBuilder      = myAssemblyBuilder.DefineDynamicModule("AdderExceptionMod", true);
            var           symbolDocumentWriter = myModuleBuilder.GetSymWriter().DefineDocument("AdderException.cil", Guid.Empty, Guid.Empty, Guid.Empty);

            TypeBuilder myTypeBuilder = myModuleBuilder.DefineType("Adder");

            Type[] adderParams = { typeof(int), typeof(int) };

            ConstructorInfo myConstructorInfo = typeof(OverflowException).GetConstructor(new[] { typeof(string) });
            MethodInfo      myExToStrMI       = typeof(OverflowException).GetMethod("ToString");
            MethodInfo      myWriteLineMI     = typeof(Console).GetMethod("WriteLine", new[] { typeof(string), typeof(object) });

            // Define method to add two numbers.
            MethodBuilder myMethodBuilder = myTypeBuilder.DefineMethod("DoAdd", MethodAttributes.Public |
                                                                       MethodAttributes.Static, typeof(int), adderParams);

            using (var il = new GroboIL(myMethodBuilder, symbolDocumentWriter))
            {
                // Declare local variable.
                GroboIL.Local myLocalBuilder1 = il.DeclareLocal(typeof(int));
                GroboIL.Local myLocalBuilder2 = il.DeclareLocal(typeof(OverflowException));

                // Define label.
                GroboIL.Label myFailedLabel      = il.DefineLabel("failed");
                GroboIL.Label myEndOfMethodLabel = il.DefineLabel("end");

                // Begin exception block.
                il.BeginExceptionBlock();

                il.Ldarg(0);
                il.Ldc_I4(10);
                il.Bgt(myFailedLabel, false);

                il.Ldarg(1);
                il.Ldc_I4(10);
                il.Bgt(myFailedLabel, false);

                il.Ldarg(0);
                il.Ldarg(1);
                il.Add_Ovf(true);
                il.Stloc(myLocalBuilder1);
                il.Leave(myEndOfMethodLabel);

                il.MarkLabel(myFailedLabel);
                il.Ldstr("Cannot accept values over 10 for add.");
                il.Newobj(myConstructorInfo);

                il.Stloc(myLocalBuilder2);
                il.Ldloc(myLocalBuilder2);

                // Throw the exception.
                il.Throw();

                // Call 'BeginExceptFilterBlock'.
                il.BeginExceptFilterBlock();
                il.WriteLine("Except filter block called.");

                // Call catch block.
                il.BeginCatchBlock(null);

                // Call other catch block.
                il.BeginCatchBlock(typeof(OverflowException));

                il.Ldstr("{0}");
                il.Ldloc(myLocalBuilder2);
                il.Call(myExToStrMI);
                il.Call(myWriteLineMI);
                il.Ldc_I4(-1);
                il.Stloc(myLocalBuilder1);

                // Call finally block.
                il.BeginFinallyBlock();
                il.WriteLine("Finally block called.");

                // End the exception block.
                il.EndExceptionBlock();

                il.MarkLabel(myEndOfMethodLabel);
                il.Ldloc(myLocalBuilder1);
                il.Ret();

                Console.WriteLine(il.GetILCode());
            }
        }
예제 #14
0
        private static Type BuildTypeInternal(Type type)
        {
            var parentType  = typeof(ValidationResultTreeNode);
            var properties  = type.GetProperties(BindingFlags.Instance | BindingFlags.Public);
            var typeBuilder = module.DefineType(type.Name + "_" + id++, TypeAttributes.Class | TypeAttributes.Public, parentType);

            typesBeingBuilt[type] = typeBuilder;

            var constructor = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, new[] { parentType });

            using (var il = new GroboIL(constructor))
            {
                il.Ldarg(0);              // stack: [this]
                il.Ldarg(1);              // stack: [this, parent]
                var baseConstructor = parentType.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { parentType }, null);
                il.Call(baseConstructor); // base(parent); stack: []
                il.Ret();
            }

            var fields = new Dictionary <string, FieldBuilder>();

            foreach (var property in properties)
            {
                var  propertyType = property.PropertyType;
                Type fieldType;
                if (propertyType.IsArray)
                {
                    fieldType = typeof(ValidationResultTreeArrayNode <>).MakeGenericType(BuildType(propertyType.GetElementType()));
                }
                else if (propertyType.IsDictionary() || propertyType == typeof(Hashtable))
                {
                    fieldType = typeof(ValidationResultTreeUniversalNode);
                }
                else
                {
                    fieldType = BuildType(propertyType, true);
                }
                var field = typeBuilder.DefineField(property.Name, fieldType, FieldAttributes.Public);
                fields.Add(property.Name, field);
            }

            var getChildrenMethod        = parentType.GetMethod("GetChildren", BindingFlags.Instance | BindingFlags.NonPublic);
            var getChildrenMethodBuilder = typeBuilder.DefineMethod(getChildrenMethod.Name, MethodAttributes.Public | MethodAttributes.Virtual, typeof(IEnumerable <KeyValuePair <object, ValidationResultTreeNode> >), Type.EmptyTypes);

            using (var il = new GroboIL(getChildrenMethodBuilder))
            {
                var listType        = typeof(List <KeyValuePair <object, ValidationResultTreeNode> >);
                var addMethod       = listType.GetMethod("Add", new[] { typeof(KeyValuePair <object, ValidationResultTreeNode>) });
                var itemConstructor = typeof(KeyValuePair <object, ValidationResultTreeNode>).GetConstructor(new[] { typeof(object), parentType });
                var list            = il.DeclareLocal(listType);
                il.Newobj(listType.GetConstructor(Type.EmptyTypes)); // stack: [new List<>()]
                il.Stloc(list);                                      // list = new List<>(); stack: []
                foreach (var field in fields.Values)
                {
                    il.Ldarg(0);                // stack: [this]
                    il.Ldfld(field);            // stack: [this.field]
                    var nextLabel = il.DefineLabel("next");
                    il.Brfalse(nextLabel);      // if(this.field == null) goto next; stack: []
                    il.Ldloc(list);             // stack: [list]
                    il.Ldstr(field.Name);       // stack: [list, field.Name]
                    il.Ldarg(0);                // stack: [list, field.Name, this]
                    il.Ldfld(field);            // stack: [list, field.Name, this.field]
                    il.Newobj(itemConstructor); // stack: [list, new KeyValuePair<object, ValidationResultTreeNode>(field.Name, this.field)]
                    il.Call(addMethod);         // list.Add(new KeyValuePair<object, ValidationResultTreeNode>(field.Name, this.field)); stack: []
                    il.MarkLabel(nextLabel);
                }

                il.Ldloc(list);
                il.Ret();
            }

            typeBuilder.DefineMethodOverride(getChildrenMethodBuilder, getChildrenMethod);

            var traverseEdgeMethod        = parentType.GetMethod("TraverseEdge", BindingFlags.Instance | BindingFlags.NonPublic);
            var traverseEdgeMethodBuilder = typeBuilder.DefineMethod(traverseEdgeMethod.Name, MethodAttributes.Public | MethodAttributes.Virtual, parentType, new[] { typeof(Expression) });

            using (var il = new GroboIL(traverseEdgeMethodBuilder))
            {
                il.Ldarg(1);                                                                   // stack: [edge]
                il.Castclass(typeof(MemberExpression));                                        // stack: [(MemberExpression)edge]
                il.Call(HackHelpers.GetProp <MemberExpression>(x => x.Member).GetGetMethod()); // stack: [((MemberExpresion)edge).Member]
                il.Call(HackHelpers.GetProp <MemberInfo>(x => x.Name).GetGetMethod());         // stack: [((MemberExpresion)edge).Member.Name]
                var member = il.DeclareLocal(typeof(string));
                il.Stloc(member);
                foreach (var property in properties)
                {
                    il.Ldstr(property.Name); // stack: [property.Name]
                    il.Ldloc(member);        // stack: [property.Name, member]
                    il.Call(typeof(string).GetMethod("op_Equality", BindingFlags.Static | BindingFlags.Public));
                    var nextLabel = il.DefineLabel("next");
                    il.Brfalse(nextLabel);           // if(property.Name != member) goto next; stack: []
                    il.Ldarg(0);                     // stack: [this]
                    il.Ldfld(fields[property.Name]); // stack: [this.field]
                    il.Ret();                        // return this.field;
                    il.MarkLabel(nextLabel);
                }

                il.Ldnull();
                il.Ret();
            }

            typeBuilder.DefineMethodOverride(traverseEdgeMethodBuilder, traverseEdgeMethod);

            var result = typeBuilder.CreateTypeInfo();

            typesBeingBuilt[type] = null;
            return(result);
        }
예제 #15
0
        private Type BuildReaderInvoker()
        {
            var argument     = Type.GetGenericArguments()[0];
            var typeBuilder  = module.DefineType("ReaderInvoker_" + Type, TypeAttributes.Public | TypeAttributes.Class);
            var reader       = typeBuilder.DefineField("reader", typeof(IntPtr), FieldAttributes.Private);
            var serializerId = typeBuilder.DefineField("serializerId", typeof(long), FieldAttributes.Private);
            var constructor  = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, new[] { typeof(IntPtr), typeof(long) });

            using (var il = new GroboIL(constructor))
            {
                il.Ldarg(0);            // stack: [this]
                il.Ldarg(1);            // stack: [this, reader]
                il.Stfld(reader);       // this.reader = reader; stack: []
                il.Ldarg(0);            // stack: [this]
                il.Ldarg(2);            // stack: [this, serializerId]
                il.Stfld(serializerId); // this.serializerId = serializerId; stack: []
                il.Ret();
            }
            var method = typeBuilder.DefineMethod("Read", MethodAttributes.Public, argument, new[] { typeof(byte[]) });

            using (var il = new GroboIL(method))
            {
                var pinnedData = il.DeclareLocal(typeof(byte).MakeByRefType(), "pinnedData", true);
                il.Ldarg(1);                                                                                                    // stack: [data]
                il.Ldc_I4(0);                                                                                                   // stack: [data, 0]
                il.Ldelema(typeof(byte));                                                                                       // stack: [&data[0]]
                il.Stloc(pinnedData);                                                                                           // pinnedData = &data[0]; stack: []
                var index = il.DeclareLocal(typeof(int), "index");
                il.Ldc_I4(0);                                                                                                   // stack: [0]
                il.Stloc(index);                                                                                                // index = 0; stack: []
                var context = il.DeclareLocal(typeof(ReaderContext), "context");
                il.Ldarg(0);                                                                                                    // stack: [this]
                il.Ldfld(serializerId);                                                                                         // stack: [this.serializerId]
                il.Ldarg(1);                                                                                                    // stack: [this.serializerId, data]
                il.Ldlen();                                                                                                     // stack: [this.serializerId, data.Length]
                il.Ldc_I4(0);                                                                                                   // stack: [this.serializerId, data.Length, 0]
                il.Ldc_I4(0);                                                                                                   // stack: [this.serializerId, data.Length, 0, 0]
                il.Newobj(typeof(ReaderContext).GetConstructor(new[] { typeof(long), typeof(int), typeof(int), typeof(int) })); // stack: [new ReaderContext(this.serializerId, data.Length, 0, 0)]
                il.Stloc(context);                                                                                              // context = new ReaderContext(..); stack: []

                var result = il.DeclareLocal(argument, "result");
                il.Ldloc(pinnedData);                                                // stack: [data]
                il.Conv <IntPtr>();                                                  // stack: [(IntPtr)data]
                il.Ldloca(index);                                                    // stack: [(IntPtr)data, ref index]
                il.Ldloca(result);                                                   // stack: [(IntPtr)data, ref index, ref result]
                il.Ldloc(context);                                                   // stack: [(IntPtr)data, ref index, ref result, context]
                il.Ldarg(0);                                                         // stack: [(IntPtr)data, ref index, ref result, context, this]
                il.Ldfld(reader);                                                    // stack: [(IntPtr)data, ref index, ref result, context, this.reader]
                var parameterTypes = new[] { typeof(IntPtr), typeof(int).MakeByRefType(), argument.MakeByRefType(), typeof(ReaderContext) };
                il.Calli(CallingConventions.Standard, typeof(void), parameterTypes); // this.reader((IntPtr)data, ref index, ref result, context); stack: []
                il.FreePinnedLocal(pinnedData);                                      // pinnedData = null; stack: []
                var retLabel = il.DefineLabel("ret");
                il.Ldarg(1);                                                         // stack: [data]
                il.Ldlen();                                                          // stack: [data.Length]
                il.Ldloc(index);                                                     // stack: [data.Length, index]
                il.Beq(retLabel);                                                    // if(data.Length == index) goto ret; stack: []
                il.Ldstr("Encountered extra data");
                il.Newobj(typeof(DataCorruptedException).GetConstructor(new[] { typeof(string) }));
                il.Throw();

                il.MarkLabel(retLabel);
                il.Ldloc(result);
                il.Ret();
            }
            return(typeBuilder.CreateType());
        }
예제 #16
0
        public void BuildReader(ReaderTypeBuilderContext readerTypeBuilderContext)
        {
            var method = new DynamicMethod("Read_" + Type.Name + "_" + Guid.NewGuid(), typeof(void),
                                           new[]
            {
                typeof(IntPtr), typeof(int).MakeByRefType(), Type.MakeByRefType(), typeof(ReaderContext)
            }, readerTypeBuilderContext.Module, true);

            readerTypeBuilderContext.SetReaderMethod(Type, method);
            using (var il = new GroboIL(method))
            {
                var context = new ReaderMethodBuilderContext(readerTypeBuilderContext, il, !Type.IsValueType && IsReference);

                ReadTypeCodeAndCheck(context); // Read TypeCode and check

                if (!Type.IsValueType && IsReference)
                {
                    // Read reference
                    context.LoadContext();                // stack: [context]
                    il.Ldfld(ReaderContext.ObjectsField); // stack: [context.objects]
                    var notReadLabel = il.DefineLabel("notRead");
                    il.Brfalse(notReadLabel);
                    context.LoadIndex();                  // stack: [external index]
                    context.LoadContext();                // stack: [external index, context]
                    il.Ldfld(ReaderContext.StartField);   // stack: [external index, context.start]
                    il.Sub();                             // stack: [external index - context.start]
                    il.Stloc(context.Index);              // index = external index - context.start; stack: []

                    context.LoadContext();                // stack: [context]
                    il.Ldfld(ReaderContext.ObjectsField); // stack: [context.objects]
                    il.Ldloc(context.Index);              // stack: [context.objects, index]
                    var obj = il.DeclareLocal(typeof(object));
                    il.Ldloca(obj);
                    object dummy;
                    il.Call(HackHelpers.GetMethodDefinition <Dictionary <int, object> >(dict => dict.TryGetValue(0, out dummy))); // stack: [context.objects.TryGetValue(index, out obj)]
                    il.Brfalse(notReadLabel);                                                                                     // if(!context.objects.TryGetValue(index, out obj)) goto notRead;
                    context.LoadResultByRef();                                                                                    // stack: [ref result]
                    il.Ldloc(obj);                                                                                                // stack: [ref result, obj]
                    il.Castclass(Type);                                                                                           // stack: [ref result, (Type)obj]
                    il.Stind(Type);                                                                                               // result = (Type)obj; stack: []
                    context.IncreaseIndexBy1();                                                                                   // Skip type code
                    context.SkipValue();                                                                                          // Skip value - it has already been read
                    il.Ret();
                    il.MarkLabel(notReadLabel);
                    il.Ldloc(context.TypeCode);               // stack: [typeCode]
                    il.Ldc_I4((int)GroBufTypeCode.Reference); // stack: [typeCode, GroBufTypeCode.Reference]
                    var readUsualLabel = il.DefineLabel("readUsual");
                    il.Bne_Un(readUsualLabel);                // if(typeCode != GroBufTypeCode.Reference) goto readUsual; stack: []

                    context.LoadContext();                    // stack: [context]
                    il.Ldfld(ReaderContext.ObjectsField);     // stack: [context.objects]
                    var objectsIsNotNullLabel = il.DefineLabel("objectsIsNotNull");
                    il.Brtrue(objectsIsNotNullLabel);         // if(context.objects != null) goto objectsIsNotNull; stack: [context.objects]
                    il.Ldstr("Reference is not valid at this point");
                    il.Newobj(typeof(DataCorruptedException).GetConstructor(new[] { typeof(string) }));
                    il.Throw();
                    il.MarkLabel(objectsIsNotNullLabel);

                    context.IncreaseIndexBy1(); // index = index + 1; stack: []
                    il.Ldc_I4(4);
                    context.AssertLength();
                    context.GoToCurrentLocation();
                    var reference = il.DeclareLocal(typeof(int));
                    il.Ldind(typeof(int));             // stack: [*(int*)data[index]]
                    il.Stloc(reference);               // reference = *(int*)data[index]; stack: []
                    context.IncreaseIndexBy4();        // index = index + 4; stack: []
                    il.Ldloc(context.Index);           // stack: [index]
                    il.Ldloc(reference);               // stack: [index, reference]
                    var goodReferenceLabel = il.DefineLabel("goodReference");
                    il.Bgt(goodReferenceLabel, false); // if(index > reference) goto goodReference; stack: []
                    il.Ldstr("Bad reference");
                    il.Newobj(typeof(DataCorruptedException).GetConstructor(new[] { typeof(string) }));
                    il.Throw();
                    il.MarkLabel(goodReferenceLabel);
                    context.LoadContext();                                                                                        // stack: [context]
                    il.Ldfld(ReaderContext.ObjectsField);                                                                         // stack: [context.objects]
                    il.Ldloc(reference);                                                                                          // stack: [context.objects, reference]
                    il.Ldloca(obj);                                                                                               // stack: [context.objects, reference, ref obj]
                    il.Call(HackHelpers.GetMethodDefinition <Dictionary <int, object> >(dict => dict.TryGetValue(0, out dummy))); // stack: [context.objects.TryGetValue(reference, out obj)]
                    var readObjectLabel = il.DefineLabel("readObject");
                    il.Brfalse(readObjectLabel);                                                                                  // if(!context.objects.TryGetValue(reference, out obj)) goto readObjects; stack: []
                    context.LoadResultByRef();                                                                                    // stack: [ref result]
                    il.Ldloc(obj);                                                                                                // stack: [ref result, obj]
                    il.Castclass(Type);                                                                                           // stack: [ref result, (Type)obj]
                    il.Stind(Type);                                                                                               // result = (Type)obj; stack: []
                    il.Ret();
                    il.MarkLabel(readObjectLabel);

                    // Referenced object has not been read - this means that the object reference belongs to is a property that had been deleted
                    context.LoadData();                 // stack: [data]
                    il.Ldloc(reference);                // stack: [data, reference]
                    context.LoadContext();              // stack: [data, reference, context]
                    il.Ldfld(ReaderContext.StartField); // stack: [data, reference, context.start]
                    il.Add();                           // stack: [data, reference + context.start]
                    il.Stloc(reference);                // reference += context.start; stack: [data]
                    il.Ldloca(reference);               // stack: [data, ref reference]
                    context.LoadResultByRef();          // stack: [data, ref reference, ref result]
                    context.LoadContext();              // stack: [data, ref reference, ref result, context]
                    context.CallReader(Type);
                    il.Ret();
                    il.MarkLabel(readUsualLabel);
                }

                ReadNotEmpty(context); // Read obj
                il.Ret();
            }
            var @delegate = method.CreateDelegate(typeof(ReaderDelegate <>).MakeGenericType(Type));
            var pointer   = GroBufHelpers.ExtractDynamicMethodPointer(method);

            readerTypeBuilderContext.SetReaderPointer(Type, pointer, @delegate);
        }
        private static void EmitValue(GroboIL il, object value)
        {
            //value.GetType() is the "real" type, only all pointers are UIntPtr and nullables are BoxedNullable
            //It can be:
            //Boolean, Char, SByte, Byte, Int16, UInt16, Int32, UInt32, Int64, UInt64, Single, Double, Decimal, DateTime, Enum, IntPtr, UIntPtr
            //Or their nullable equivalents
            //Or string
            switch (value)
            {
            case bool boolean: il.Ldc_I4(boolean ? 1 : 0); break;

            case char character: il.Ldc_I4(character); break;

            case sbyte int8: il.Ldc_I4(int8); break;

            case byte uint8: il.Ldc_I4(uint8); break;

            case short int16: il.Ldc_I4(int16); break;

            case ushort uint16: il.Ldc_I4(uint16); break;

            case int int32: il.Ldc_I4(int32); break;

            case uint uint32: il.Ldc_I4((int)uint32); break;

            case long int64: il.Ldc_I8(int64); break;

            case ulong uint64: il.Ldc_I8((long)uint64); break;

            case float float32: il.Ldc_R4(float32); break;

            case double float64: il.Ldc_R8(float64); break;

            case decimal decimal128: il.LdDec(decimal128); break;

            case DateTime dateTime:
                var local = il.DeclareLocal(typeof(DateTime));
                il.Ldloca(local);
                il.Ldc_I8(dateTime.Ticks);
                il.Ldc_I4((int)dateTime.Kind);
                il.Call(typeof(DateTime).GetConstructor(new[] { typeof(long), typeof(DateTimeKind) }));
                il.Ldloc(local);
                break;

            case UIntPtr unint: il.Ldc_IntPtr(Unsafe.As <UIntPtr, IntPtr>(ref unint)); break;

            case IntPtr nint: il.Ldc_IntPtr(nint); break;

            case Enum enumeration:
                var underlyingType  = Enum.GetUnderlyingType(enumeration.GetType());
                var underlyingValue = Convert.ChangeType(enumeration, underlyingType);
                EmitValue(il, underlyingValue);
                break;

            case BoxedNullable boxedNullable:
                EmitValue(il, boxedNullable.UnderlyingValue);
                il.Newobj(boxedNullable.NullableType.GetConstructor(new[] { boxedNullable.UnderlyingType }));
                break;

            case string str: il.Ldstr(str); break;

            default: throw new ArgumentException($"Value {value} of type {value.GetType()} is not supported by the emitter.");
            }
        }
예제 #18
0
        public void BuildWriter(WriterTypeBuilderContext writerTypeBuilderContext)
        {
            var method = new DynamicMethod("Write_" + Type.Name + "_" + Guid.NewGuid(), typeof(void),
                                           new[]
            {
                Type, typeof(bool), typeof(IntPtr), typeof(int).MakeByRefType(), typeof(WriterContext)
            }, writerTypeBuilderContext.Module, true);

            writerTypeBuilderContext.SetWriterMethod(Type, method);
            using (var il = new GroboIL(method))
            {
                var context = new WriterMethodBuilderContext(writerTypeBuilderContext, il);

                var notEmptyLabel = il.DefineLabel("notEmpty");
                if (CheckEmpty(context, notEmptyLabel)) // Check if obj is empty
                {
                    context.WriteNull();                // Write null & return
                }
                il.MarkLabel(notEmptyLabel);            // Now we know that obj is not empty

                if (!Type.IsValueType && IsReference && writerTypeBuilderContext.GroBufWriter.Options.HasFlag(GroBufOptions.PackReferences))
                {
                    // Pack reference
                    var index = il.DeclareLocal(typeof(int));
                    context.LoadIndex();                                                                                             // stack: [external index]
                    context.LoadContext();                                                                                           // stack: [external index, context]
                    il.Ldfld(WriterContext.StartField);                                                                              // stack: [external index, context.start]
                    il.Sub();                                                                                                        // stack: [external index - context.start]
                    il.Stloc(index);                                                                                                 // index = external index - context.start; stack: []
                    context.LoadContext();                                                                                           // stack: [context]
                    il.Ldfld(typeof(WriterContext).GetField("objects", BindingFlags.Public | BindingFlags.Instance));                // stack: [context.objects]
                    context.LoadObj();                                                                                               // stack: [context.objects, obj]
                    var reference = il.DeclareLocal(typeof(int));
                    il.Ldloca(reference);                                                                                            // stack: [context.objects, obj, ref reference]
                    int dummy;
                    il.Call(HackHelpers.GetMethodDefinition <Dictionary <object, int> >(dict => dict.TryGetValue(null, out dummy))); // stack: [context.object.TryGetValue(obj, out reference)]
                    var storeLocationLabel = il.DefineLabel("storeLocation");
                    il.Brfalse(storeLocationLabel);
                    // Current object is in dict
                    il.Ldloc(index);
                    il.Ldloc(reference);                             // stack: [index, reference]
                    var skipSelfLabel = il.DefineLabel("skipSelf");
                    il.Beq(skipSelfLabel);                           // if(index == reference) goto skipSelf; stack: []
                    il.Ldloc(index);                                 // stack: [index]
                    il.Ldloc(reference);                             // stack: [index, reference]
                    var badReferenceLabel = il.DefineLabel("badReference");
                    il.Blt(badReferenceLabel, false);                // if(index < reference) goto badReference; stack: []
                    context.WriteTypeCode(GroBufTypeCode.Reference); // result[index++] = GroBufTypeCode.Reference
                    context.GoToCurrentLocation();                   // stack: [&result[index]]
                    il.Ldloc(reference);                             // stack: [&result[index], reference]
                    il.Stind(typeof(int));                           // *(int *)&result[index] = reference
                    context.IncreaseIndexBy4();                      // index += 4
                    il.Ret();
                    il.MarkLabel(badReferenceLabel);
                    il.Ldstr("Bad reference");
                    il.Newobj(typeof(DataCorruptedException).GetConstructor(new[] { typeof(string) }));
                    il.Throw();
                    il.MarkLabel(storeLocationLabel);
                    context.LoadContext();                                                                            // stack: [context]
                    il.Ldfld(typeof(WriterContext).GetField("objects", BindingFlags.Public | BindingFlags.Instance)); // stack: [context.objects]
                    context.LoadObj();                                                                                // stack: [context.objects, obj]
                    il.Ldloc(index);                                                                                  // stack: [context.objects, obj, index]
                    il.Call(HackHelpers.GetMethodDefinition <Dictionary <object, int> >(dict => dict.Add(null, 0)));  // context.objects.Add(obj, index);
                    il.MarkLabel(skipSelfLabel);
                }

                WriteNotEmpty(context); // Write obj
                il.Ret();
            }
            var @delegate = method.CreateDelegate(typeof(WriterDelegate <>).MakeGenericType(Type));
            var pointer   = GroBufHelpers.ExtractDynamicMethodPointer(method);

            writerTypeBuilderContext.SetWriterPointer(Type, pointer, @delegate);
        }
예제 #19
0
        public void Test3()
        {
            // Create an assembly.
            AssemblyName myAssemblyName = new AssemblyName();

            myAssemblyName.Name = "AdderExceptionAsm";

            // Create dynamic assembly.
            AppDomain       myAppDomain       = Thread.GetDomain();
            AssemblyBuilder myAssemblyBuilder = myAppDomain.DefineDynamicAssembly(myAssemblyName,
                                                                                  AssemblyBuilderAccess.Run);

            // Create a dynamic module.
            ModuleBuilder myModuleBuilder      = myAssemblyBuilder.DefineDynamicModule("AdderExceptionMod", true);
            var           symbolDocumentWriter = myModuleBuilder.GetSymWriter().DefineDocument("AdderException.cil", Guid.Empty, Guid.Empty, Guid.Empty);
            TypeBuilder   myTypeBuilder        = myModuleBuilder.DefineType("Adder");

            Type[] myAdderParams = new Type[] { typeof(int), typeof(int) };

            // Create constructor.
            ConstructorInfo myConstructorInfo = typeof(OverflowException).GetConstructor(
                new Type[] { typeof(string) });
            MethodInfo myExToStrMI   = typeof(OverflowException).GetMethod("ToString");
            MethodInfo myWriteLineMI = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string), typeof(object) });

            // Method to add two numbers.
            MethodBuilder myMethodBuilder = myTypeBuilder.DefineMethod("DoAdd", MethodAttributes.Public |
                                                                       MethodAttributes.Static, typeof(int), myAdderParams);

            using (var il = new GroboIL(myMethodBuilder, symbolDocumentWriter))
            {
                // Declare local variable.
                GroboIL.Local myLocalBuilder1 = il.DeclareLocal(typeof(int));
                GroboIL.Local myLocalBuilder2 = il.DeclareLocal(typeof(OverflowException));

                // Define label.
                GroboIL.Label myFailedLabel      = il.DefineLabel("failed");
                GroboIL.Label myEndOfMethodLabel = il.DefineLabel("end");

                // Begin exception block.
                il.BeginExceptionBlock();

                il.Ldarg(0);
                il.Ldc_I4(10);
                il.Bgt(myFailedLabel, false);

                il.Ldarg(1);
                il.Ldc_I4(10);
                il.Bgt(myFailedLabel, false);

                il.Ldarg(0);
                il.Ldarg(1);
                il.Add_Ovf(true);
                il.Stloc(myLocalBuilder1);
                il.Br(myEndOfMethodLabel);

                il.MarkLabel(myFailedLabel);
                il.Ldstr("Cannot accept values over 10 for addition.");
                il.Newobj(myConstructorInfo);

                il.Stloc(myLocalBuilder2);
                il.Ldloc(myLocalBuilder2);

                // Call fault block.
                il.BeginFaultBlock();
                //Throw exception.
                il.Newobj(typeof(NotSupportedException).GetConstructor(Type.EmptyTypes));
                il.Throw();

                // Call finally block.
                il.BeginFinallyBlock();

                il.Ldstr("{0}");
                il.Ldloc(myLocalBuilder2);
                il.Call(myExToStrMI);
                il.Call(myWriteLineMI);
                il.Ldc_I4(-1);
                il.Stloc(myLocalBuilder1);

                // End exception block.
                il.EndExceptionBlock();

                il.MarkLabel(myEndOfMethodLabel);
                il.Ldloc(myLocalBuilder1);
                il.Ret();

                Console.WriteLine(il.GetILCode());
            }

            Type adderType = myTypeBuilder.CreateType();

            object addIns = Activator.CreateInstance(adderType);

            object[] addParams = new object[2];

            addParams[0] = 20;

            addParams[1] = 10;

            Console.WriteLine("{0} + {1} = {2}",
                              addParams[0], addParams[1],
                              adderType.InvokeMember("DoAdd",
                                                     BindingFlags.InvokeMethod,
                                                     null,
                                                     addIns,
                                                     addParams));
        }