Пример #1
0
        internal static void AddMethod(MethodInfo mi, TypeCreationContext context, bool hasImplementation)
        {
            // Get all the parameters to the method
            var parameterTypes = mi.GetParameters().Select(pi => pi.ParameterType).ToArray();

            var mBuilder = context.TypeBuilder.DefineMethod(mi.Name, MethodAttributes.Public | MethodAttributes.Virtual, mi.ReturnType, parameterTypes);

            context.Methods.Add(mi.Name, mBuilder);

            var mGenerator = mBuilder.GetILGenerator();

            if (hasImplementation)
            {
                if (mi.ReturnType == typeof(void))
                {
                    AddVoidDelegateInvocation(mi, context, parameterTypes, mGenerator);
                }
                else
                {
                    AddDelegateInvocation(mi, context, parameterTypes, mGenerator);
                }
            }
            else if (mi.ReturnType != typeof(void))
            {
                var localBuilder = mGenerator.DeclareLocal(mi.ReturnType);

                mGenerator.Emit(OpCodes.Ldloc, localBuilder);
            }

            mGenerator.Emit(OpCodes.Ret);
        }
Пример #2
0
        static void Main(string[] args)
        {
            var context = TypeCreationContext.ImplementInterface <TestInterface>();

            context.AddImplementation <int, int>("DoBar", i => i * 2);
            context.AddImplementation("DoFoo", () => Console.WriteLine("Doing this from a void implementation"));

            var obj = context.CreateInstance() as TestInterface;

            var obj2 = TypeCreationContext.New <TestInterface>();

            if (obj != null)
            {
                obj.Foo = "Foo";

                Console.WriteLine(obj.Foo);
                Console.WriteLine(obj.Bar);

                obj.DoFoo();
                obj.DoFooAgain(1, 2);

                Console.WriteLine(obj.DoBar(3));
                Console.WriteLine(obj.DoFoobar("5", 3, 1));
            }

            Console.ReadLine();
        }
Пример #3
0
        private static void AddVoidDelegateInvocation(MethodInfo mi, TypeCreationContext context, Type[] parameterTypes, ILGenerator mGenerator)
        {
            mGenerator.DeclareLocal(DELEGATE_TYPE);

            bool hasParameters = parameterTypes != null && parameterTypes.Length > 0;

            if (hasParameters)
            {
                mGenerator.DeclareLocal(OBJ_ARR_TYPE);
                mGenerator.DeclareLocal(OBJ_ARR_TYPE);
            }

            mGenerator.Emit(OpCodes.Nop);
            mGenerator.Emit(OpCodes.Ldarg_0);
            mGenerator.Emit(OpCodes.Ldfld, context.Fields[METHOD_DICTIONARY]);
            mGenerator.Emit(OpCodes.Ldstr, mi.Name);

            var dictGetMethod = DEL_DICT_TYPE.GetMethod("get_Item", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);

            mGenerator.Emit(OpCodes.Callvirt, dictGetMethod);
            mGenerator.Emit(OpCodes.Stloc_0);

            // Now if we need to deal with parameters lets do this now
            if (hasParameters)
            {
                OpCode arraySize = GetSizeOpCode(parameterTypes.Length);

                mGenerator.Emit(arraySize);

                mGenerator.Emit(OpCodes.Newarr, OBJ_TYPE);
                mGenerator.Emit(OpCodes.Stloc_2);
                mGenerator.Emit(OpCodes.Ldloc_2);

                for (int i = 0; i < parameterTypes.Length; i++)
                {
                    mGenerator.Emit(GetSizeOpCode(i));
                    mGenerator.Emit(GetArgumentOpCode(i + 1));

                    if (parameterTypes[i].IsValueType)
                    {
                        mGenerator.Emit(OpCodes.Box, GetBoxedType(parameterTypes[i]));
                    }

                    mGenerator.Emit(OpCodes.Stelem_Ref);
                    mGenerator.Emit(OpCodes.Ldloc_2);
                }

                mGenerator.Emit(OpCodes.Stloc_1);
            }

            // Generate the IL to call the delegate properly
            mGenerator.Emit(OpCodes.Ldloc_0);
            mGenerator.Emit(hasParameters ? OpCodes.Ldloc_1 : OpCodes.Ldnull);
            mGenerator.Emit(OpCodes.Callvirt, DELEGATE_TYPE.GetMethod("DynamicInvoke"));

            // Return from the method properly
            mGenerator.Emit(OpCodes.Pop);
            mGenerator.Emit(OpCodes.Ret);
        }
Пример #4
0
        private static void AddDelegateInvocation(MethodInfo mi, TypeCreationContext context, Type[] parameterTypes, ILGenerator mGenerator)
        {
            mGenerator.DeclareLocal(DELEGATE_TYPE);            // reference to delegate to call
            mGenerator.DeclareLocal(OBJ_ARR_TYPE);             // Delegate parameter array
            mGenerator.DeclareLocal(mi.ReturnType);            // Return type
            mGenerator.DeclareLocal(OBJ_ARR_TYPE);             // ??? I think its the parameter array that goes on the stack to call the delegate

            // Generate the IL to get the delegate out of the private dictionary
            mGenerator.Emit(OpCodes.Nop);
            mGenerator.Emit(OpCodes.Ldarg_0);
            mGenerator.Emit(OpCodes.Ldfld, context.Fields[METHOD_DICTIONARY]);
            mGenerator.Emit(OpCodes.Ldstr, mi.Name);

            var dictGetMethod = DEL_DICT_TYPE.GetMethod("get_Item", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);

            mGenerator.Emit(OpCodes.Callvirt, dictGetMethod);
            mGenerator.Emit(OpCodes.Stloc_0);

            // Create the parameter array
            OpCode arraySize = GetSizeOpCode(parameterTypes.Length);

            mGenerator.Emit(arraySize);

            mGenerator.Emit(OpCodes.Newarr, OBJ_TYPE);
            mGenerator.Emit(OpCodes.Stloc_3);
            mGenerator.Emit(OpCodes.Ldloc_3);

            // Add each parameter to the array
            for (int i = 0; i < parameterTypes.Length; i++)
            {
                mGenerator.Emit(GetSizeOpCode(i));
                mGenerator.Emit(GetArgumentOpCode(i + 1));

                if (parameterTypes[i].IsValueType)
                {
                    mGenerator.Emit(OpCodes.Box, GetBoxedType(parameterTypes[i]));
                }

                mGenerator.Emit(OpCodes.Stelem_Ref);
                mGenerator.Emit(OpCodes.Ldloc_3);
            }

            // Copy the array over to the location 1
            mGenerator.Emit(OpCodes.Stloc_1);

            // Generate the IL to call the delegate
            mGenerator.Emit(OpCodes.Ldloc_0);
            mGenerator.Emit(OpCodes.Ldloc_1);
            mGenerator.Emit(OpCodes.Callvirt, DELEGATE_TYPE.GetMethod("DynamicInvoke"));

            mGenerator.Emit(OpCodes.Unbox_Any, mi.ReturnType);
            mGenerator.Emit(OpCodes.Stloc_2);

            // Load the value for return purposes
            mGenerator.Emit(OpCodes.Nop);
            mGenerator.Emit(OpCodes.Ldloc_2);
        }
Пример #5
0
        internal static void AddDefaultConstructor(TypeCreationContext context, bool hasImplementations)
        {
            var ci = typeof(object).GetConstructor(Type.EmptyTypes);

            var cBuilder = context.TypeBuilder.DefineConstructor(MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, CallingConventions.Standard, Type.EmptyTypes);

            var generator = cBuilder.GetILGenerator();

            generator.Emit(OpCodes.Ldarg_0);

            if (hasImplementations)
            {
                generator.Emit(OpCodes.Newobj, typeof(Dictionary <string, Delegate>).GetConstructor(Type.EmptyTypes));

                var fieldBuilder = context.Fields[METHOD_DICTIONARY];

                generator.Emit(OpCodes.Stfld, fieldBuilder);

                generator.Emit(OpCodes.Ldarg_0);
            }

            generator.Emit(OpCodes.Call, ci);
            generator.Emit(OpCodes.Ret);
        }
Пример #6
0
        internal static void AddProperty(PropertyInfo pi, TypeCreationContext context)
        {
            var backingFieldName = "_" + pi.Name;

            var fieldBuilder = context.TypeBuilder.DefineField(backingFieldName, pi.PropertyType, FieldAttributes.Private);

            context.Fields.Add(backingFieldName, fieldBuilder);

            var propertyBuilder = context.TypeBuilder.DefineProperty(pi.Name, pi.Attributes, pi.PropertyType, null);

            context.Properties.Add(pi.Name, propertyBuilder);

            var methodAttributes = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig;

            var getter = pi.GetGetMethod();

            if (getter != null)
            {
                if (getter.IsFinal)
                {
                    methodAttributes |= MethodAttributes.Final;
                }

                var gmMethodBuilder = context.TypeBuilder.DefineMethod("get_" + pi.Name, methodAttributes | MethodAttributes.Virtual, pi.PropertyType, Type.EmptyTypes);

                context.Methods.Add(gmMethodBuilder.Name, gmMethodBuilder);

                var gmGenerator = gmMethodBuilder.GetILGenerator();

                gmGenerator.Emit(OpCodes.Ldarg_0);
                gmGenerator.Emit(OpCodes.Ldfld, fieldBuilder);
                gmGenerator.Emit(OpCodes.Ret);

                propertyBuilder.SetGetMethod(gmMethodBuilder);

                context.TypeBuilder.DefineMethodOverride(gmMethodBuilder, getter);
            }

            var setter = pi.GetSetMethod();

            if (setter != null)
            {
                if (setter.IsVirtual)
                {
                    methodAttributes |= MethodAttributes.Virtual;
                }

                var smMethodBuilder = context.TypeBuilder.DefineMethod("set_" + pi.Name, methodAttributes, null, new Type[] { pi.PropertyType });

                context.Methods.Add(smMethodBuilder.Name, smMethodBuilder);

                var smGenerator = smMethodBuilder.GetILGenerator();

                smGenerator.Emit(OpCodes.Ldarg_0);                 // This is equivalent to "this"
                smGenerator.Emit(OpCodes.Ldarg_1);                 // This is the typical "value" parameter
                smGenerator.Emit(OpCodes.Stfld, fieldBuilder);
                smGenerator.Emit(OpCodes.Ret);

                propertyBuilder.SetSetMethod(smMethodBuilder);

                context.TypeBuilder.DefineMethodOverride(smMethodBuilder, setter);
            }
        }
Пример #7
0
        internal static void AddImplementationsDictionary(TypeCreationContext context)
        {
            var dictionaryField = context.TypeBuilder.DefineField(METHOD_DICTIONARY, typeof(IDictionary <string, Delegate>), FieldAttributes.Private);

            context.Fields.Add(METHOD_DICTIONARY, dictionaryField);
        }