예제 #1
0
		// TODO: merge method and mb
		public ReturnParameter (MemberCore method, MethodBuilder mb, Location location)
		{
			this.method = method;
			try {
				builder = mb.DefineParameter (0, ParameterAttributes.None, "");			
			}
			catch (ArgumentOutOfRangeException) {
				method.Compiler.Report.RuntimeMissingSupport (location, "custom attributes on the return type");
			}
		}
예제 #2
0
					internal override void ApplyReturnValue(ClassLoaderWrapper loader, MethodBuilder mb, ref ParameterBuilder pb, object annotation)
					{
						// TODO make sure the descriptor is correct
						Annotation ann = type.Annotation;
						object[] arr = (object[])annotation;
						for (int i = 2; i < arr.Length; i += 2)
						{
							if ("value".Equals(arr[i]))
							{
								if (pb == null)
								{
									pb = mb.DefineParameter(0, ParameterAttributes.None, null);
								}
								object[] value = (object[])arr[i + 1];
								if (value[0].Equals(AnnotationDefaultAttribute.TAG_ANNOTATION))
								{
									ann.Apply(loader, pb, value);
								}
								else
								{
									for (int j = 1; j < value.Length; j++)
									{
										ann.Apply(loader, pb, value[j]);
									}
								}
								break;
							}
						}
					}
예제 #3
0
		public virtual void ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index, PredefinedAttributes pa)
		{
			if (builder != null)
				throw new InternalErrorException ("builder already exists");

			var pattrs = ParametersCompiled.GetParameterAttribute (modFlags);
			if (HasOptionalExpression)
				pattrs |= ParameterAttributes.Optional;

			if (mb == null)
				builder = cb.DefineParameter (index, pattrs, Name);
			else
				builder = mb.DefineParameter (index, pattrs, Name);

			if (OptAttributes != null)
				OptAttributes.Emit ();

			if (HasDefaultValue) {
				//
				// Emit constant values for true constants only, the other
				// constant-like expressions will rely on default value expression
				//
				var def_value = DefaultValue;
				Constant c = def_value != null ? def_value.Child as Constant : default_expr as Constant;
				if (c != null) {
					if (c.Type.BuiltinType == BuiltinTypeSpec.Type.Decimal) {
						pa.DecimalConstant.EmitAttribute (builder, (decimal) c.GetValue (), c.Location);
					} else {
						builder.SetConstant (c.GetValue ());
					}
				} else if (default_expr.Type.IsStruct) {
					//
					// Handles special case where default expression is used with value-type
					//
					// void Foo (S s = default (S)) {}
					//
					builder.SetConstant (null);
				}
			}

			if (parameter_type != null) {
				if (parameter_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
					pa.Dynamic.EmitAttribute (builder);
				} else if (parameter_type.HasDynamicElement) {
					pa.Dynamic.EmitAttribute (builder, parameter_type, Location);
				}
			}
		}
예제 #4
0
        /// <summary>
        /// Generates a method on our <see cref="TypeBuilder"/> for the specified <see cref="MethodInfo"/>
        /// </summary>
        /// <param name="tb">The <see cref="TypeBuilder"/> we're generating our type with.</param>
        /// <param name="mi">The <see cref="MethodInfo"/> which represents the "template" method.</param>
        /// <param name="dllName">The path to the DLL that we'll put in the <see cref="DllImportAttribute"/>.</param>
        private static void GenerateMethod(TypeBuilder tb, MethodInfo mi, string dllName)
        {
            // These are all the parameters in our method
            List <ParameterInfo> pis = new List <ParameterInfo>(mi.GetParameters());

            // We need to keep the parameter types and attributes in a separate array.
            Type[] ptypes = new Type[pis.Count];
            ParameterAttributes[] attrs = new ParameterAttributes[pis.Count];
            for (int i = 0; i < pis.Count; i++)
            {
                ptypes[i] = pis[i].ParameterType;
                attrs[i]  = pis[i].Attributes;
            }

            // We actually need to create TWO methods - one for the interface implementation, and one for the
            // P/Invoke declaration. We'll create the P/Invoke definition first.
            MethodBuilder smb = tb.DefineMethod(
                mi.Name,                 // The name is the same as the interface name
                // P/Invoke methods need special attributes...
                MethodAttributes.Static | MethodAttributes.Private | MethodAttributes.HideBySig,
                mi.ReturnType, ptypes);

            // Get the type of the DllImportAttribute, which we'll attach to this method
            Type diaType = typeof(DllImportAttribute);

            // Create a CustomAttributeBuilder for the DLLImportAttribute, specifying the constructor that takes a string argument.
            ConstructorInfo        ctor = diaType.GetConstructor(new Type[] { typeof(string) });
            CustomAttributeBuilder cab  = new CustomAttributeBuilder(ctor, new object[] { dllName });

            // Assign the DllImport attribute to the smb
            smb.SetCustomAttribute(cab);

            // Also, any attributes on the actual parameters need to be copied to the P/Invoke declaration as well.
            for (int i = 0; i < attrs.Length; i++)
            {
                smb.DefineParameter(i + 1, attrs[i], pis[i].Name);
            }

            // Now create the interface implementation method
            MethodBuilder mb = tb.DefineMethod(
                "IFbClient." + mi.Name,                 // We use the standard "Interface.Method" to do an explicit interface implementation
                MethodAttributes.Private | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual |
                MethodAttributes.Final,
                mi.ReturnType, ptypes);

            // Also, any attributes on the actual parameters need to be copied to the P/Invoke declaration as well.
            for (int i = 0; i < attrs.Length; i++)
            {
                mb.DefineParameter(i + 1, attrs[i], pis[i].Name);
            }

            // We need to generate a little IL here to actually call the P/Invoke declaration. Luckily for us, since we're just
            // going to pass our parameters to the P/Invoke method as-is, we don't need to muck with the eval stack ;-)
            ILGenerator il = mb.GetILGenerator();

            for (int i = 1; i <= pis.Count; i++)
            {
                if (i == 1)
                {
                    il.Emit(OpCodes.Ldarg_1);
                }
                else if (i == 2)
                {
                    il.Emit(OpCodes.Ldarg_2);
                }
                else if (i == 3)
                {
                    il.Emit(OpCodes.Ldarg_3);
                }
                else
                {
                    il.Emit(OpCodes.Ldarg_S, (short)i);
                }
            }

            il.EmitCall(OpCodes.Call, smb, null);
            il.Emit(OpCodes.Ret);

            // Define the fact that our IFbClient.Method is the explicit interface implementation of that method
            tb.DefineMethodOverride(mb, mi);
        }
예제 #5
0
        private static void BuildMethodEquals(TypeBuilder type, FieldInfo equalsHasBeenCalled, FieldInfo comparer)
        {
            var           methodAttributes = MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig;
            MethodBuilder method           = type.DefineMethod("Equals", methodAttributes);

            MethodInfo objectEquals = typeof(object).GetMethod(
                "Equals",
                BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
                null,
                new[] { typeof(object) },
                null
                );

            MethodInfo equalityComparerEquals = typeof(IEqualityComparer).GetMethod(
                "Equals",
                BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
                null,
                new[] { typeof(object), typeof(object) },
                null
                );

            method.SetReturnType(typeof(bool));
            method.SetParameters(typeof(object));
            method.DefineParameter(1, ParameterAttributes.None, "obj");

            ILGenerator gen = method.GetILGenerator();

            gen.DeclareLocal(typeof(bool));
            gen.DeclareLocal(typeof(bool));

            Label label1 = gen.DefineLabel();
            Label label2 = gen.DefineLabel();

            gen.Emit(OpCodes.Nop);
            gen.Emit(OpCodes.Ldarg_0);
            gen.Emit(OpCodes.Ldfld, equalsHasBeenCalled);
            gen.Emit(OpCodes.Ldc_I4_0);
            gen.Emit(OpCodes.Ceq);
            gen.Emit(OpCodes.Stloc_1);
            gen.Emit(OpCodes.Ldloc_1);
            gen.Emit(OpCodes.Brtrue_S, label1);
            gen.Emit(OpCodes.Nop);
            gen.Emit(OpCodes.Ldarg_0);
            gen.Emit(OpCodes.Ldc_I4_0);
            gen.Emit(OpCodes.Stfld, equalsHasBeenCalled);
            gen.Emit(OpCodes.Ldarg_0);
            gen.Emit(OpCodes.Ldarg_1);
            gen.Emit(OpCodes.Call, objectEquals);
            gen.Emit(OpCodes.Stloc_0);
            gen.Emit(OpCodes.Br_S, label2);
            gen.MarkLabel(label1);
            gen.Emit(OpCodes.Ldarg_0);
            gen.Emit(OpCodes.Ldc_I4_1);
            gen.Emit(OpCodes.Stfld, equalsHasBeenCalled);
            gen.Emit(OpCodes.Ldarg_0);
            gen.Emit(OpCodes.Ldfld, comparer);
            gen.Emit(OpCodes.Ldarg_0);
            gen.Emit(OpCodes.Ldarg_1);
            gen.Emit(OpCodes.Callvirt, equalityComparerEquals);
            gen.Emit(OpCodes.Stloc_0);
            gen.Emit(OpCodes.Br_S, label2);
            gen.MarkLabel(label2);
            gen.Emit(OpCodes.Ldloc_0);
            gen.Emit(OpCodes.Ret);
        }
        private MethodBuilder CreateMethodOverride(MethodBuilder delegateMethod)
        {
            string methodName =
                this.explicitImplementation
                        ? methodToOverride.DeclaringType.Name + "." + methodToOverride.Name
                        : methodToOverride.Name;

            MethodBuilder methodBuilder =
                typeBuilder.DefineMethod(
                    methodName,
                    this.explicitImplementation ? explicitImplementationAttributes : implicitImplementationAttributes);

            var paramMapper = new MethodOverrideParameterMapper(methodToOverride);

            paramMapper.SetupParameters(methodBuilder);

            methodBuilder.SetReturnType(paramMapper.GetReturnType());
            methodBuilder.SetParameters(methodParameters.Select(pi => paramMapper.GetParameterType(pi.ParameterType)).ToArray());
            if (this.explicitImplementation)
            {
                this.typeBuilder.DefineMethodOverride(methodBuilder, this.methodToOverride);
            }

            int paramNum = 1;

            foreach (ParameterInfo pi in methodParameters)
            {
                methodBuilder.DefineParameter(paramNum++, pi.Attributes, pi.Name);
            }

            ILGenerator il = methodBuilder.GetILGenerator();

            LocalBuilder methodReturn   = il.DeclareLocal(typeof(IMethodReturn));
            LocalBuilder ex             = il.DeclareLocal(typeof(Exception));
            LocalBuilder parameterArray = il.DeclareLocal(typeof(object[]));
            LocalBuilder inputs         = il.DeclareLocal(typeof(VirtualMethodInvocation));

            // Create instance of VirtualMethodInvocation
            il.Emit(OpCodes.Ldarg_0); // target object

            // If we have a targetField, that means we're building a proxy and
            // should use it as the target object. If we don't, we're building
            // a type interceptor and should leave the this pointer as the
            // target.
            if (targetField != null)
            {
                il.Emit(OpCodes.Ldfld, targetField);
            }

            il.Emit(OpCodes.Ldtoken, methodToOverride);
            if (methodToOverride.DeclaringType.IsGenericType)
            {
                il.Emit(OpCodes.Ldtoken, methodToOverride.DeclaringType);
                il.Emit(OpCodes.Call, MethodBaseMethods.GetMethodForGenericFromHandle);
            }
            else
            {
                il.Emit(OpCodes.Call, MethodBaseMethods.GetMethodFromHandle); // target method
            }

            EmitLoadConstant(il, methodParameters.Length);
            il.Emit(OpCodes.Newarr, typeof(object)); // object[] parameters
            if (methodParameters.Length > 0)
            {
                il.Emit(OpCodes.Stloc, parameterArray);

                for (int i = 0; i < methodParameters.Length; ++i)
                {
                    il.Emit(OpCodes.Ldloc, parameterArray);
                    EmitLoadConstant(il, i);
                    EmitLoadArgument(il, i);
                    Type elementType = paramMapper.GetParameterType(methodParameters[i].ParameterType);
                    if (elementType.IsByRef)
                    {
                        elementType = paramMapper.GetElementType(methodParameters[i].ParameterType);
                        il.Emit(OpCodes.Ldobj, elementType);
                    }
                    EmitBox(il, elementType);
                    il.Emit(OpCodes.Stelem_Ref);
                }

                il.Emit(OpCodes.Ldloc, parameterArray);
            }
            il.Emit(OpCodes.Newobj, VirtualMethodInvocationMethods.VirtualMethodInvocation);
            il.Emit(OpCodes.Stloc, inputs);

            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Ldfld, proxyInterceptionPipelineField);
            il.Emit(OpCodes.Ldloc, inputs);

            // Put delegate reference onto the stack
            il.Emit(OpCodes.Ldarg_0);

            MethodInfo callTarget = delegateMethod;

            if (callTarget.IsGenericMethod)
            {
                callTarget = delegateMethod.MakeGenericMethod(paramMapper.MappedGenericParameters);
            }

            il.Emit(OpCodes.Ldftn, callTarget);

            il.Emit(OpCodes.Newobj, InvokeInterceptionBehaviorDelegateMethods.InvokeInterceptionBehaviorDelegate);

            // And call the pipeline
            il.Emit(OpCodes.Call, InterceptionBehaviorPipelineMethods.Invoke);

            il.Emit(OpCodes.Stloc, methodReturn);

            // Was there an exception?
            Label noException = il.DefineLabel();

            il.Emit(OpCodes.Ldloc, methodReturn);
            il.EmitCall(OpCodes.Callvirt, IMethodReturnMethods.GetException, null);
            il.Emit(OpCodes.Stloc, ex);
            il.Emit(OpCodes.Ldloc, ex);
            il.Emit(OpCodes.Ldnull);
            il.Emit(OpCodes.Ceq);
            il.Emit(OpCodes.Brtrue_S, noException);
            il.Emit(OpCodes.Ldloc, ex);
            il.Emit(OpCodes.Throw);

            il.MarkLabel(noException);

            // Unpack any ref/out parameters
            if (methodParameters.Length > 0)
            {
                int outputArgNum = 0;
                for (paramNum = 0; paramNum < methodParameters.Length; ++paramNum)
                {
                    ParameterInfo pi = methodParameters[paramNum];
                    if (pi.ParameterType.IsByRef)
                    {
                        // Get the original parameter value - address of the ref or out
                        EmitLoadArgument(il, paramNum);

                        // Get the value of this output parameter out of the Outputs collection
                        il.Emit(OpCodes.Ldloc, methodReturn);
                        il.Emit(OpCodes.Callvirt, IMethodReturnMethods.GetOutputs);
                        EmitLoadConstant(il, outputArgNum++);
                        il.Emit(OpCodes.Callvirt, IListMethods.GetItem);
                        EmitUnboxOrCast(il, paramMapper.GetElementType(pi.ParameterType));

                        // And store in the caller
                        il.Emit(OpCodes.Stobj, paramMapper.GetElementType(pi.ParameterType));
                    }
                }
            }

            if (MethodHasReturnValue)
            {
                il.Emit(OpCodes.Ldloc, methodReturn);
                il.EmitCall(OpCodes.Callvirt, IMethodReturnMethods.GetReturnValue, null);
                EmitUnboxOrCast(il, ReturnType);
            }
            il.Emit(OpCodes.Ret);

            return(methodBuilder);
        }
예제 #7
0
        public EventLogger(object item)
        {
            if (item == null)
            {
                throw new ArgumentNullException("item");
            }

            log = new EventLog();

            Type         itemType = item.GetType();
            AssemblyName name     = new AssemblyName();

            name.Name = "EventLoggerAssembly";
            AssemblyBuilder assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.RunAndSave);
            ModuleBuilder   module   = assembly.DefineDynamicModule("EventLoggerAssembly", "EventLoggerAssembly.dll");

            Type ListType = log.GetType();

            TypeBuilder        logType  = module.DefineType("Logger");
            FieldBuilder       logField = logType.DefineField("log", ListType, FieldAttributes.Public);
            ConstructorBuilder logCtor  = logType.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, new Type [] { ListType, itemType });

            logCtor.DefineParameter(1, ParameterAttributes.None, "test");
            logCtor.DefineParameter(2, ParameterAttributes.None, "obj");
            ILGenerator logIL = logCtor.GetILGenerator();

            logIL.Emit(OpCodes.Ldarg_0);
            logIL.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes));

            logIL.Emit(OpCodes.Ldarg_0);
            logIL.Emit(OpCodes.Ldarg_1);
            logIL.Emit(OpCodes.Stfld, logField);


            foreach (EventInfo Event in itemType.GetEvents())
            {
                ILGenerator il;

                MethodInfo    invoke = Event.EventHandlerType.GetMethod("Invoke");
                MethodBuilder method = logType.DefineMethod(Event.Name, MethodAttributes.Public, null, new Type [] { invoke.GetParameters() [0].ParameterType, invoke.GetParameters() [1].ParameterType });
                method.DefineParameter(1, ParameterAttributes.None, "test");
                method.DefineParameter(2, ParameterAttributes.None, "test2");
                il = method.GetILGenerator();
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldfld, logField);
                il.Emit(OpCodes.Ldstr, Event.Name);
                il.Emit(OpCodes.Callvirt, ListType.GetMethod("Add"));
                il.Emit(OpCodes.Pop);
                il.Emit(OpCodes.Ret);

                logIL.Emit(OpCodes.Ldarg_2);
                logIL.Emit(OpCodes.Ldarg_0);
                logIL.Emit(OpCodes.Dup);
                logIL.Emit(OpCodes.Ldvirtftn, method);
                logIL.Emit(OpCodes.Newobj, Event.EventHandlerType.GetConstructor(new Type [] { typeof(object), typeof(IntPtr) }));
                logIL.Emit(OpCodes.Call, Event.GetAddMethod());
            }

            logIL.Emit(OpCodes.Ret);
            Type builtLogType = logType.CreateType();

            instance = builtLogType.GetConstructors() [0].Invoke(new object [] { log, item });
            TestHelper.RemoveWarning(instance);

            //assembly.Save ("EventLoggerAssembly.dll");
        }
예제 #8
0
        static void BuildMethod(
            TypeBuilder tb,
            string methodName,
            string rpcMethodName,
            string[] paramNames,
            Type[] argTypes,
            bool paramsMethod,
            Type returnType,
            bool structParams)
        {
            MethodBuilder mthdBldr = tb.DefineMethod(
                methodName,
                MethodAttributes.Public | MethodAttributes.Virtual,
                returnType, argTypes);

            // add attribute to method
            Type[] oneString = new Type[1] {
                typeof(string)
            };
            Type            methodAttr = typeof(XmlRpcMethodAttribute);
            ConstructorInfo ci         = methodAttr.GetConstructor(oneString);

            PropertyInfo[] pis
                = new PropertyInfo[] { methodAttr.GetProperty("StructParams") };
            object[] structParam       = new object[] { structParams };
            CustomAttributeBuilder cab =
                new CustomAttributeBuilder(ci, new object[] { rpcMethodName },
                                           pis, structParam);

            mthdBldr.SetCustomAttribute(cab);
            for (int i = 0; i < paramNames.Length; i++)
            {
                ParameterBuilder paramBldr = mthdBldr.DefineParameter(i + 1,
                                                                      ParameterAttributes.In, paramNames[i]);
                // possibly add ParamArrayAttribute to final parameter
                if (i == paramNames.Length - 1 && paramsMethod)
                {
                    ConstructorInfo ctorInfo = typeof(ParamArrayAttribute).GetConstructor(
                        new Type[0]);
                    CustomAttributeBuilder attrBldr =
                        new CustomAttributeBuilder(ctorInfo, new object[0]);
                    paramBldr.SetCustomAttribute(attrBldr);
                }
            }
            // generate IL
            ILGenerator ilgen = mthdBldr.GetILGenerator();
            // if non-void return, declared locals for processing return value
            LocalBuilder retVal     = null;
            LocalBuilder tempRetVal = null;

            if (typeof(void) != returnType)
            {
                tempRetVal = ilgen.DeclareLocal(typeof(System.Object));
                retVal     = ilgen.DeclareLocal(returnType);
            }
            // declare variable to store method args and emit code to populate ut
            LocalBuilder argValues = ilgen.DeclareLocal(typeof(System.Object[]));

            ilgen.Emit(OpCodes.Ldc_I4, argTypes.Length);
            ilgen.Emit(OpCodes.Newarr, typeof(System.Object));
            ilgen.Emit(OpCodes.Stloc, argValues);
            for (int argLoad = 0; argLoad < argTypes.Length; argLoad++)
            {
                ilgen.Emit(OpCodes.Ldloc, argValues);
                ilgen.Emit(OpCodes.Ldc_I4, argLoad);
                ilgen.Emit(OpCodes.Ldarg, argLoad + 1);
                if (argTypes[argLoad].IsValueType)
                {
                    ilgen.Emit(OpCodes.Box, argTypes[argLoad]);
                }
                ilgen.Emit(OpCodes.Stelem_Ref);
            }
            // call Invoke on base class
            Type[]     invokeTypes = new Type[] { typeof(MethodInfo), typeof(object[]) };
            MethodInfo invokeMethod
                = typeof(XmlRpcClientProtocol).GetMethod("Invoke", invokeTypes);

            ilgen.Emit(OpCodes.Ldarg_0);
            ilgen.Emit(OpCodes.Call, typeof(MethodBase).GetMethod("GetCurrentMethod"));
            ilgen.Emit(OpCodes.Castclass, typeof(System.Reflection.MethodInfo));
            ilgen.Emit(OpCodes.Ldloc, argValues);
            ilgen.Emit(OpCodes.Call, invokeMethod);
            //  if non-void return prepare return value, otherwise pop to discard
            if (typeof(void) != returnType)
            {
                // if return value is null, don't cast it to required type
                Label retIsNull = ilgen.DefineLabel();
                ilgen.Emit(OpCodes.Stloc, tempRetVal);
                ilgen.Emit(OpCodes.Ldloc, tempRetVal);
                ilgen.Emit(OpCodes.Brfalse, retIsNull);
                ilgen.Emit(OpCodes.Ldloc, tempRetVal);
                if (true == returnType.IsValueType)
                {
                    ilgen.Emit(OpCodes.Unbox, returnType);
                    ilgen.Emit(OpCodes.Ldobj, returnType);
                }
                else
                {
                    ilgen.Emit(OpCodes.Castclass, returnType);
                }
                ilgen.Emit(OpCodes.Stloc, retVal);
                ilgen.MarkLabel(retIsNull);
                ilgen.Emit(OpCodes.Ldloc, retVal);
            }
            else
            {
                ilgen.Emit(OpCodes.Pop);
            }
            ilgen.Emit(OpCodes.Ret);
        }
        private MethodBuilder CreateDelegateImplementation()
        {
            string methodName = CreateMethodName("DelegateImplementation");

            MethodBuilder methodBuilder = typeBuilder.DefineMethod(methodName,
                                                                   MethodAttributes.Private | MethodAttributes.HideBySig);
            List <LocalBuilder> outOrRefLocals = new List <LocalBuilder>();

            var paramMapper = new MethodOverrideParameterMapper(methodToOverride);

            paramMapper.SetupParameters(methodBuilder);

            methodBuilder.SetReturnType(typeof(IMethodReturn));
            // Adding parameters
            methodBuilder.SetParameters(typeof(IMethodInvocation), typeof(GetNextInterceptionBehaviorDelegate));
            // Parameter
            methodBuilder.DefineParameter(1, ParameterAttributes.None, "inputs");
            // Parameter
            methodBuilder.DefineParameter(2, ParameterAttributes.None, "getNext");

            methodBuilder.SetCustomAttribute(new CustomAttributeBuilder(CompilerGeneratedAttributeMethods.CompilerGeneratedAttribute, new object[0]));

            ILGenerator il = methodBuilder.GetILGenerator();

            if (this.targetField != null)
            {
                #region forwarding implementation

                Label        done = il.DefineLabel();
                LocalBuilder ex   = il.DeclareLocal(typeof(Exception));

                LocalBuilder baseReturn = null;
                LocalBuilder parameters = null;

                if (MethodHasReturnValue)
                {
                    baseReturn = il.DeclareLocal(paramMapper.GetReturnType());
                }
                LocalBuilder retval = il.DeclareLocal(typeof(IMethodReturn));

                il.BeginExceptionBlock();
                // Call the target method
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldfld, targetField);

                if (methodParameters.Length > 0)
                {
                    parameters = il.DeclareLocal(typeof(IParameterCollection));
                    il.Emit(OpCodes.Ldarg_1);
                    il.EmitCall(OpCodes.Callvirt, IMethodInvocationMethods.GetArguments, null);
                    il.Emit(OpCodes.Stloc, parameters);

                    for (int i = 0; i < methodParameters.Length; ++i)
                    {
                        il.Emit(OpCodes.Ldloc, parameters);
                        EmitLoadConstant(il, i);
                        il.EmitCall(OpCodes.Callvirt, IListMethods.GetItem, null);
                        Type parameterType = paramMapper.GetParameterType(methodParameters[i].ParameterType);

                        if (parameterType.IsByRef)
                        {
                            Type         elementType    = parameterType.GetElementType();
                            LocalBuilder refShadowLocal = il.DeclareLocal(elementType);
                            outOrRefLocals.Add(refShadowLocal);
                            EmitUnboxOrCast(il, elementType);
                            il.Emit(OpCodes.Stloc, refShadowLocal);
                            il.Emit(OpCodes.Ldloca, refShadowLocal);
                        }
                        else
                        {
                            EmitUnboxOrCast(il, parameterType);
                        }
                    }
                }

                MethodInfo callTarget = methodToOverride;
                if (callTarget.IsGenericMethod)
                {
                    callTarget = methodToOverride.MakeGenericMethod(paramMapper.MappedGenericParameters);
                }

                il.Emit(OpCodes.Callvirt, callTarget);

                if (MethodHasReturnValue)
                {
                    il.Emit(OpCodes.Stloc, baseReturn);
                }

                // Generate  the return value
                il.Emit(OpCodes.Ldarg_1);
                if (MethodHasReturnValue)
                {
                    il.Emit(OpCodes.Ldloc, baseReturn);
                    EmitBox(il, ReturnType);
                }
                else
                {
                    il.Emit(OpCodes.Ldnull);
                }
                EmitLoadConstant(il, methodParameters.Length);
                il.Emit(OpCodes.Newarr, typeof(object));

                if (methodParameters.Length > 0)
                {
                    LocalBuilder outputArguments = il.DeclareLocal(typeof(object[]));
                    il.Emit(OpCodes.Stloc, outputArguments);

                    int outputArgNum = 0;
                    for (int i = 0; i < methodParameters.Length; ++i)
                    {
                        il.Emit(OpCodes.Ldloc, outputArguments);
                        EmitLoadConstant(il, i);

                        Type parameterType = paramMapper.GetParameterType(methodParameters[i].ParameterType);
                        if (parameterType.IsByRef)
                        {
                            parameterType = parameterType.GetElementType();
                            il.Emit(OpCodes.Ldloc, outOrRefLocals[outputArgNum++]);
                            EmitBox(il, parameterType);
                        }
                        else
                        {
                            il.Emit(OpCodes.Ldloc, parameters);
                            EmitLoadConstant(il, i);
                            il.Emit(OpCodes.Callvirt, IListMethods.GetItem);
                        }
                        il.Emit(OpCodes.Stelem_Ref);
                    }
                    il.Emit(OpCodes.Ldloc, outputArguments);
                }

                il.Emit(OpCodes.Callvirt, IMethodInvocationMethods.CreateReturn);
                il.Emit(OpCodes.Stloc, retval);
                il.BeginCatchBlock(typeof(Exception));
                il.Emit(OpCodes.Stloc, ex);
                // Create an exception return
                il.Emit(OpCodes.Ldarg_1);
                il.Emit(OpCodes.Ldloc, ex);
                il.EmitCall(OpCodes.Callvirt, IMethodInvocationMethods.CreateExceptionMethodReturn, null);
                il.Emit(OpCodes.Stloc, retval);
                il.EndExceptionBlock();
                il.MarkLabel(done);
                il.Emit(OpCodes.Ldloc, retval);
                il.Emit(OpCodes.Ret);

                #endregion
            }
            else
            {
                #region exception-throwing implementation

                il.Emit(OpCodes.Ldarg_1);
                il.EmitCall(OpCodes.Call, BuildAdditionalInterfaceNonImplementedExceptionMethod, null);
                il.EmitCall(OpCodes.Callvirt, IMethodInvocationMethods.CreateExceptionMethodReturn, null);
                il.Emit(OpCodes.Ret);

                #endregion
            }
            return(methodBuilder);
        }
예제 #10
0
        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 (_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 (!_useLRE)
            {
                MethodBuilder methBldr = _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, Array.Empty <object>()));
                    methBldr.SetCustomAttribute(new CustomAttributeBuilder(XmlILConstructors.NonUserCode, Array.Empty <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, s_LREModule);
                methDyn.InitLocals = true;

                methResult = methDyn;
            }

            // Index method by name
            _methods[name] = methResult;
            return(methResult);
        }
예제 #11
0
        static void GenerateFields(object fields, string n, RecordTypeDescriptor rtd, TypeGen tg, object fieldtypes)
        {
            object[] f      = RequiresNotNull <object[]>(fields);
            object[] ftypes = RequiresNotNull <object[]>(fieldtypes);

            List <FieldDescriptor> rtd_fields = new List <FieldDescriptor>();

            for (int i = 0; i < f.Length; i++)
            {
                Cons c = (Cons)f[i];
                // check for recursive definition
                Type t = rtd.Name == SymbolTable.IdToString((SymbolId)ftypes[i]) ?
                         rtd.tg.TypeBuilder :
                         ClrGenerator.ExtractTypeInfo(List(SymbolTable.StringToObject("quote"), ftypes[i]));

                // can this ever be null given ExtractTypeInfo throws?
                if (t == null)
                {
                    ClrGenerator.ClrSyntaxError("GenerateFields", "type not found", ftypes[i]);
                }

                string fname = SymbolTable.IdToString(RequiresNotNull <SymbolId>(Second(c)));
                // we use standard names here, they will be mapped to the given names
                string aname = n + "-" + fname;
                string mname = n + "-" + fname + "-set!";

                var fd = new FieldDescriptor {
                    Name = fname
                };

                FieldAttributes fattrs = FieldAttributes.Public;// | FieldAttributes.InitOnly;
                if (c.car == SymbolTable.StringToObject("mutable"))
                {
                    fd.mutable = true;
                    //fattrs &= ~FieldAttributes.InitOnly;
                }
                FieldSlot s = tg.AddField(t, fname, fattrs) as FieldSlot;

                fd.field = s.Field;

                PropertyBuilder pi = tg.TypeBuilder.DefineProperty(fname, PropertyAttributes.None, t, new Type[0]);

                // accesor

                MethodBuilder ab = tg.TypeBuilder.DefineMethod(aname, MethodAttributes.Public | MethodAttributes.Static,
                                                               t, new Type[] { tg.TypeBuilder });

                ab.DefineParameter(1, ParameterAttributes.None, n);

                ILGenerator agen = ab.GetILGenerator();
                agen.Emit(OpCodes.Ldarg_0);
                //agen.Emit(OpCodes.Castclass, tg.TypeBuilder);
                agen.Emit(OpCodes.Ldfld, fd.field);
                agen.Emit(OpCodes.Ret);

                fd.accessor = ab;
                pi.SetGetMethod(ab);

                // mutator
                if (fd.mutable)
                {
                    MethodBuilder mb = tg.TypeBuilder.DefineMethod(mname, MethodAttributes.Public | MethodAttributes.Static,
                                                                   typeof(object), new Type[] { tg.TypeBuilder, t });

                    mb.DefineParameter(1, ParameterAttributes.None, n);

                    ILGenerator mgen = mb.GetILGenerator();
                    mgen.Emit(OpCodes.Ldarg_0);
                    //mgen.Emit(OpCodes.Castclass, tg.TypeBuilder);
                    mgen.Emit(OpCodes.Ldarg_1);
                    mgen.Emit(OpCodes.Stfld, fd.field);
                    mgen.Emit(OpCodes.Ldsfld, Compiler.Generator.Unspecified);
                    mgen.Emit(OpCodes.Ret);

                    fd.mutator = mb;
                    pi.SetSetMethod(mb);
                }

                rtd_fields.Add(fd);
            }

            rtd.fields = rtd_fields.ToArray();
        }
예제 #12
0
        /// <summary>
        /// Emits a method to complement an interface method. The complement method will have a suffix such as _Completed,
        /// and will take one parameter.
        /// </summary>
        /// <param name="invocationContext">The InvocationContext for this call.</param>
        /// <param name="suffix">The suffix to use on the method.</param>
        /// <param name="parameterType">The type of the parameter of the method.</param>
        /// <param name="parameterName">The name of the parameter of the method.</param>
        /// <param name="beginMethod">The begin method for this interface call.</param>
        /// <param name="eventId">The next available event ID.</param>
        /// <param name="autoKeyword">The auto-keyword to use if enabled.</param>
        /// <param name="faultedMethod">A faulted method to call or null if no other faulted method is available.</param>
        /// <returns>The MethodBuilder for the method.</returns>
        private MethodBuilder EmitMethodComplementImpl(InvocationContext invocationContext, string suffix, Type parameterType, string parameterName, MethodInfo beginMethod, ref int eventId, EventKeywords autoKeyword, MethodBuilder faultedMethod, List <Tuple <FieldInfo, object> > valuesToSet)
        {
            var interfaceMethod = invocationContext.MethodInfo;

            // if there is a NonEvent attribute, then no need to emit this method
            if (interfaceMethod.GetCustomAttribute <NonEventAttribute>() != null)
            {
                return(null);
            }

            // if the method ends in _Completed, then don't emit another one
            if (interfaceMethod.Name.EndsWith(suffix, StringComparison.OrdinalIgnoreCase))
            {
                return(null);
            }

            var methodName = beginMethod.Name + suffix;

            // if the interface already has a _Completed method with the same parameter, don't emit a new one
            var parameterTypes = parameterType == typeof(void) ? Type.EmptyTypes : new Type[] { parameterType };

            if (interfaceMethod.DeclaringType.GetMethod(methodName, parameterTypes) != null)
            {
                return(null);
            }

            // create a single parameter for the return value, and a context parameter if its supported
            var parameterMappings = new List <ParameterMapping>();

            if (parameterType != typeof(void))
            {
                var mapping = new ParameterMapping(parameterName);
                mapping.AddSource(new ParameterDefinition(parameterName, 0, parameterType));
                parameterMappings.Add(mapping);
            }

            if (SupportsContext(invocationContext))
            {
                parameterMappings.Add(new ParameterMapping(Context));
            }

            // determine if this is a non-event or an event
            // if an event, but there is no event attribute, just add one to the last event id
            EventAttribute startEventAttribute = interfaceMethod.GetCustomAttribute <EventAttribute>() ?? new EventAttribute(eventId);
            EventAttribute eventAttribute      = _eventAttributeProvider.CopyEventAttribute(startEventAttribute, invocationContext, eventId);

            eventId = Math.Max(eventId, eventAttribute.EventId + 1);
            if (eventAttribute.Keywords == EventKeywords.None)
            {
                eventAttribute.Keywords = autoKeyword;
            }

            // define the internal method
            MethodBuilder m = _typeBuilder.DefineMethod(methodName, MethodAttributes.Public, typeof(void), parameterMappings.Select(p => p.CleanTargetType).ToArray());

            if (parameterMappings.Any())
            {
                m.DefineParameter(1, ParameterAttributes.None, parameterMappings[0].Name);
            }
            m.SetCustomAttribute(EventAttributeHelper.ConvertEventAttributeToAttributeBuilder(eventAttribute));

            // if we have a return type, then we need to implement two methods
            if (parameterTypes.Length == 1)
            {
                EmitCallWriteEvent(invocationContext, m, eventAttribute, parameterMappings);

                // emit an overloaded wrapper method that calls the method when it's enabled
                // note this is a non-event so EventSource doesn't try to log it
                MethodBuilder im = _typeBuilder.DefineMethod(methodName, MethodAttributes.Public);
                ProxyHelper.CopyGenericSignature(interfaceMethod, im);
                im.SetReturnType(parameterTypes[0]);
                im.SetParameters(parameterTypes);

                // mark the method as a non-event
                im.SetCustomAttribute(EventAttributeHelper.CreateNonEventAttribute());

                // put the return value on the stack so we can return the value as a passthrough
                im.GetILGenerator().Emit(OpCodes.Ldarg_1);

                if (EmitIsEnabled(im, eventAttribute))
                {
                    EmitTaskCompletion(im, parameterType, faultedMethod);
                    EmitDirectProxy(invocationContext, im, m, parameterMappings, valuesToSet);
                }

                return(im);
            }
            else
            {
                // the method does not have a return value
                // so create the internal method that calls WriteEvent
                ProxyHelper.EmitDefaultValue(m.GetILGenerator(), m.ReturnType);
                if (EmitIsEnabled(m, eventAttribute))
                {
                    EmitCallWriteEvent(invocationContext, m, eventAttribute, parameterMappings);
                }

                return(m);
            }
        }
예제 #13
0
        /// <summary>
        /// Emits an implementation of a given method.
        /// </summary>
        /// <param name="invocationContext">The InvocationContext for this call.</param>
        /// <param name="eventId">The next eventID to use.</param>
        /// <param name="autoKeyword">The auto-keyword to use if enabled.</param>
        /// <returns>The method that is implemented.</returns>
        private MethodBuilder EmitMethodImpl(InvocationContext invocationContext, ref int eventId, EventKeywords autoKeyword, List <Tuple <FieldInfo, object> > valuesToSet)
        {
            // get the method we are implementing and the parameter mapping
            var interfaceMethod  = invocationContext.MethodInfo;
            var parameterMapping = _traceParameterProvider.ProvideParameterMapping(invocationContext.MethodInfo).Where(p => p.HasSource).ToList();

            // if we are implementing an interface, then add an string context parameter
            if (SupportsContext(invocationContext))
            {
                parameterMapping.Add(new ParameterMapping(Context));
            }

            // calculate the method name
            // if there is more than one method with the given name, then append an ID to it
            var methodName      = interfaceMethod.Name;
            var matchingMethods = interfaceMethod.DeclaringType.GetMethods().AsEnumerable().Where(im => String.Compare(im.Name, methodName, StringComparison.OrdinalIgnoreCase) == 0).ToArray();

            if (matchingMethods.Length > 1)
            {
                methodName += "_" + Array.IndexOf(matchingMethods, interfaceMethod).ToString(CultureInfo.InvariantCulture);
            }

            // determine if this is a non-event or an event
            // if an event, but there is no event attribute, just add one to the last event id
            EventAttribute eventAttribute = null;

            if (interfaceMethod.GetCustomAttribute <NonEventAttribute>() == null)
            {
                eventAttribute = _eventAttributeProvider.GetEventAttribute(invocationContext, eventId, parameterMapping);
                eventId        = Math.Max(eventId, eventAttribute.EventId + 1);
            }

            // if auto-keywords are enabled, use them
            if (eventAttribute != null && eventAttribute.Keywords == EventKeywords.None)
            {
                eventAttribute.Keywords = autoKeyword;
            }

            ValidateEventMessage(eventAttribute, interfaceMethod, parameterMapping);

            // create the internal method that calls WriteEvent
            // this cannot be virtual or static, or the manifest builder will skip it
            // it also cannot return a value
            MethodBuilder m = _typeBuilder.DefineMethod(methodName, MethodAttributes.Public, typeof(void), parameterMapping.Select(p => p.CleanTargetType).ToArray());

            // copy the Event or NonEvent attribute from the interface
            if (eventAttribute != null)
            {
                m.SetCustomAttribute(EventAttributeHelper.ConvertEventAttributeToAttributeBuilder(eventAttribute));
            }
            else
            {
                m.SetCustomAttribute(EventAttributeHelper.CreateNonEventAttribute());
            }

            // add the parameter names
            for (int i = 0; i < parameterMapping.Count; i++)
            {
                var parameter = parameterMapping[i];
                m.DefineParameter(i + 1, ParameterAttributes.In, parameter.Name);
            }

            if (interfaceMethod.IsAbstract || !interfaceMethod.DeclaringType.IsSubclassOf(typeof(EventSource)))
            {
                // for interface methods, implement a call to write event
                ProxyHelper.EmitDefaultValue(m.GetILGenerator(), m.ReturnType);
                if (EmitIsEnabled(m, eventAttribute))
                {
                    EmitCallWriteEvent(invocationContext, m, eventAttribute, parameterMapping);
                }

                // since EventSource only accepts non-virtual methods, and we need a virtual method to implement the abstract method
                // we need to implement a wrapper method on the interface that calls into the base method
                // and handles the bundling/unbundling of parameters
                MethodBuilder im = _typeBuilder.DefineMethod("_" + methodName, MethodAttributes.Public | MethodAttributes.Virtual);
                ProxyHelper.CopyMethodSignature(interfaceMethod, im);
                ProxyHelper.EmitDefaultValue(im.GetILGenerator(), im.ReturnType);
                if (EmitIsEnabled(im, eventAttribute))
                {
                    EmitDirectProxy(invocationContext, im, m, parameterMapping, valuesToSet);
                }

                // if this is an interface, then tell the system to map our method to the interface implementation
                if (interfaceMethod.IsAbstract)
                {
                    _typeBuilder.DefineMethodOverride(im, interfaceMethod);
                }
            }
            else
            {
                // we are implementing a non-abstract method in event source, then
                // all we can do is call the base implementation
                EmitDirectProxy(invocationContext, m, interfaceMethod, parameterMapping, valuesToSet);
            }

            return(m);
        }
예제 #14
0
        protected virtual MethodBuilder CreateProxyMethod(TypeBuilder typeBuilder, MethodInfo method, MethodFilterAttribute[] classFilters, MethodFilterAttribute[] methodFilters, FieldBuilder[] staticFields, int startFilterIndex, Func <MethodFilterAttribute, bool> predicate)
        {
            ILGenerator generator = null;

            Type typeParameter = null;

            Type[] typeParameters = null;
            GenericTypeParameterBuilder typeParameterBuilder = null;

            GenericTypeParameterBuilder[] typeParameterBuilders = null;

            MethodBuilder methodBuilder   = null;
            ParameterInfo methodParameter = null;

            ParameterInfo[] methodParameters = method.GetParameters();
            LocalBuilder    contextVariableBuilder = null, exceptionVariableBuilder = null, returnVariableBuilder = null;
            Label           checkCancelLabel, callBaseMethodLabel;

            // create method
            MethodAttributes methodAttributes = (method.IsPublic ? MethodAttributes.Public : MethodAttributes.Family) | MethodAttributes.Virtual;

            if (method.IsSpecialName)
            {
                methodAttributes |= MethodAttributes.SpecialName;
            }
            methodBuilder = typeBuilder.DefineMethod(method.Name, methodAttributes, CallingConventions.Standard, method.ReturnType, methodParameters.Select((item) => item.ParameterType).ToArray());
            this.InjectCustomAttributes(method, methodBuilder);

            // create method type arguments
            if (method.IsGenericMethodDefinition || method.IsGenericMethod && method.ContainsGenericParameters)
            {
                typeParameters = method.GetGenericArguments().Where((item) => item.IsGenericParameter).ToArray();
                if (typeParameters.Length > 0)
                {
                    typeParameterBuilders = methodBuilder.DefineGenericParameters(typeParameters.Select((item) => item.Name).ToArray());

                    for (int j = 0; j < typeParameters.Length; j++)
                    {
                        typeParameter        = typeParameters[j];
                        typeParameterBuilder = typeParameterBuilders[j];

                        typeParameterBuilder.SetGenericParameterAttributes(typeParameter.GenericParameterAttributes);
                        foreach (Type constraint in typeParameter.GetGenericParameterConstraints())
                        {
                            if (constraint.IsClass)
                            {
                                typeParameterBuilder.SetBaseTypeConstraint(constraint);
                            }
                            else
                            {
                                typeParameterBuilder.SetInterfaceConstraints(constraint);
                            }
                        }
                    }
                }
            }

            // create method parameters
            for (int j = 0; j < methodParameters.Length; j++)
            {
                this.InjectCustomAttributes(
                    methodParameters[j],
                    methodBuilder.DefineParameter(j + 1, methodParameters[j].Attributes, methodParameters[j].Name));
            }

            // delcare local variables
            generator = methodBuilder.GetILGenerator();
            contextVariableBuilder   = generator.DeclareLocal(typeof(MethodExecutingContext), false);
            exceptionVariableBuilder = generator.DeclareLocal(typeof(Exception), false);
            if (!method.ReturnType.Equals(typeof(void)))
            {
                returnVariableBuilder = generator.DeclareLocal(method.ReturnType, false);
            }

            // initialize local variables
            generator.Emit(OpCodes.Ldarg_0);
            generator.Emit(OpCodes.Ldstr, method.ReflectedType.FullName);
            generator.Emit(OpCodes.Ldstr, method.Name);
            generator.Emit(OpCodes.Ldstr, method.ToString());
            generator.Emit(OpCodes.Newobj, g_contextConstructor);
            generator.Emit(OpCodes.Stloc_0);

            // initialize arguments of context variable
            for (int j = 0; j < methodParameters.Length; j++)
            {
                if ((methodParameter = methodParameters[j]).IsOut)
                {
                    continue;
                }

                generator.Emit(OpCodes.Ldloc_0);
                generator.Emit(OpCodes.Ldstr, methodParameter.Name);
                generator.Emit(OpCodes.Ldarg, j + 1);
                if (methodParameter.ParameterType.IsValueType)
                {
                    generator.Emit(OpCodes.Box, methodParameter.ParameterType);
                }
                generator.Emit(OpCodes.Callvirt, g_contextAddArgumentMethod);
            }

            // invoke OnPreExecuting
            for (int j = 0; j < classFilters.Length; j++)
            {
                if (!predicate(classFilters[j]))
                {
                    continue;
                }

                generator.Emit(OpCodes.Ldsfld, staticFields[j]);
                generator.Emit(OpCodes.Ldloc_0);
                generator.Emit(OpCodes.Callvirt, g_onPreExecutingMethod);
            }
            for (int j = 0; j < methodFilters.Length; j++)
            {
                if (!predicate(methodFilters[j]))
                {
                    continue;
                }

                generator.Emit(OpCodes.Ldsfld, staticFields[startFilterIndex + j]);
                generator.Emit(OpCodes.Ldloc_0);
                generator.Emit(OpCodes.Callvirt, g_onPreExecutingMethod);
            }

            // check Exception property
            generator.BeginExceptionBlock();
            generator.Emit(OpCodes.Ldloc_0);
            generator.Emit(OpCodes.Callvirt, g_contextExceptionGetter);
            generator.Emit(OpCodes.Brfalse_S, checkCancelLabel = generator.DefineLabel());
            generator.Emit(OpCodes.Ldloc_0);
            generator.Emit(OpCodes.Callvirt, g_contextExceptionGetter);
            generator.Emit(OpCodes.Throw);

            // check IsCancel property
            generator.MarkLabel(checkCancelLabel);
            generator.Emit(OpCodes.Ldloc_0);
            generator.Emit(OpCodes.Callvirt, g_contextIsCancelGetter);
            generator.Emit(OpCodes.Brfalse_S, callBaseMethodLabel = generator.DefineLabel());
            generator.Emit(OpCodes.Newobj, g_canceledExceptionConstructor);
            generator.Emit(OpCodes.Throw);

            // call current method
            generator.BeginExceptionBlock();
            generator.MarkLabel(callBaseMethodLabel);
            generator.Emit(OpCodes.Ldarg_0);
            for (int j = 1; j <= methodParameters.Length; j++)
            {
                generator.Emit(OpCodes.Ldarg, j);
            }
            generator.Emit(OpCodes.Call, method);
            if (!method.ReturnType.Equals(typeof(void)))
            {
                generator.Emit(OpCodes.Stloc_2);
            }

            // catch Exception
            generator.BeginCatchBlock(typeof(Exception));
            generator.Emit(OpCodes.Stloc_1);
            generator.Emit(OpCodes.Ldloc_0);
            generator.Emit(OpCodes.Ldloc_1);
            generator.Emit(OpCodes.Callvirt, g_contextExceptionSetter);
            generator.Emit(OpCodes.Ldloc_1);
            generator.Emit(OpCodes.Throw);
            generator.EndExceptionBlock();

            // invoke OnPostExecuting
            generator.BeginFinallyBlock();
            for (int j = 0; j < methodFilters.Length; j++)
            {
                if (!predicate(methodFilters[j]))
                {
                    continue;
                }

                generator.Emit(OpCodes.Ldsfld, staticFields[startFilterIndex + j]);
                generator.Emit(OpCodes.Ldloc_0);
                generator.Emit(OpCodes.Callvirt, g_onPostExecutingMethod);
            }
            for (int j = 0; j < classFilters.Length; j++)
            {
                if (!predicate(classFilters[j]))
                {
                    continue;
                }

                generator.Emit(OpCodes.Ldsfld, staticFields[j]);
                generator.Emit(OpCodes.Ldloc_0);
                generator.Emit(OpCodes.Callvirt, g_onPostExecutingMethod);
            }
            generator.EndExceptionBlock();

            if (!method.ReturnType.Equals(typeof(void)))
            {
                generator.Emit(OpCodes.Ldloc_2);
            }
            generator.Emit(OpCodes.Ret);

            return(methodBuilder);
        }
예제 #15
0
        void IMethodReflector.Build(MethodBuilder builder)
        {
            if (_method == null)
            {
                throw new InvalidOperationException();
            }

            builder.Name       = Name;
            builder.Idempotent = Idempotent;

            //
            // Build the method parameters.
            //

            MethodInfo method = _method;

            ParameterInfo[] parameters = method.GetParameters();

            if (method.IsStatic)
            {
                ParameterInfo[] logicalParameters = new ParameterInfo[parameters.Length - 1];
                Array.Copy(parameters, 1, logicalParameters, 0, logicalParameters.Length);
                parameters = logicalParameters;
            }

            if (WarpedParameters)
            {
                if (parameters.Length != 1)
                {
                    // TODO: Use a more specific exception type
                    throw new Exception(string.Format(
                                            "Methods using warped parameters must accept a single argument of the warped type whereas method {1} on {0} accepts {2}.",
                                            method.DeclaringType.FullName, method.Name, parameters.Length.ToString()));
                }

                PropertyDescriptorCollection args = GetProperties(parameters[0].ParameterType);
                foreach (PropertyDescriptor arg in args)
                {
                    ParameterBuilder parameter = builder.DefineParameter();
                    parameter.Name          = arg.Name;
                    parameter.ParameterType = arg.PropertyType;
                }

                PropertyDescriptor result = null;

                if (method.ReturnType != typeof(void))
                {
                    PropertyDescriptorCollection results = GetProperties(method.ReturnType);
                    if (results.Count > 0)
                    {
                        result             = results[0];
                        builder.ResultType = result.PropertyType;
                    }
                }

                builder.Handler = new WarpedMethodImpl(builder.Handler,
                                                       parameters[0].ParameterType,
                                                       args, result);
            }
            else
            {
                foreach (ParameterInfo parameter in parameters)
                {
                    JsonRpcServiceReflector.BuildParameter(builder.DefineParameter(), parameter);
                }
            }
        }
예제 #16
0
        /// <summary>
        /// 动态构造targetType的代理类
        /// </summary>
        /// <returns></returns>
        public static Type BuildProxy(Type targetType, bool declaredOnly = false)
        {
            //创建一个类型
            if (targetType.IsInterface)
            {
                throw new Exception("cannot create a proxy class for the interface");
            }
            Type TypeOfParent = targetType;

            Type[]       TypeOfInterfaces = new Type[0];
            TypeBuilder  typeBuilder      = modBuilder.DefineType(targetType.Name + "Proxy" + Guid.NewGuid().ToString("N"), TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.BeforeFieldInit, TypeOfParent, TypeOfInterfaces);
            BindingFlags bindingFlags;

            if (declaredOnly)
            {
                bindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly;
            }
            else
            {
                bindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
            }
            MethodInfo[] targetMethods = targetType.GetMethods(bindingFlags);
            //遍历各个方法
            foreach (MethodInfo targetMethod in targetMethods)
            {
                //只挑出virtual的实例方法进行重写
                //只挑出打了RewriteAttribute标记的方法进行重写
                if (targetMethod.IsVirtual && !targetMethod.IsStatic && !targetMethod.IsFinal && !targetMethod.IsAssembly && targetMethod.GetCustomAttributes(true).Any(e => (e as RewriteAttribute != null)))
                {
                    Type[]          paramType;
                    Type            returnType;
                    ParameterInfo[] paramInfo;
                    Type            delegateType    = GetDelegateType(targetMethod, out paramType, out returnType, out paramInfo);
                    Type            interceptorType = typeof(T);
                    MethodBuilder   methodBuilder   = typeBuilder.DefineMethod(targetMethod.Name, MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.Final | MethodAttributes.HideBySig, returnType, paramType);
                    for (var i = 0; i < paramInfo.Length; i++)
                    {
                        ParameterBuilder paramBuilder = methodBuilder.DefineParameter(i + 1, paramInfo[i].Attributes, paramInfo[i].Name);
                        if (paramInfo[i].HasDefaultValue)
                        {
                            paramBuilder.SetConstant(paramInfo[i].DefaultValue);
                        }
                    }
                    ILGenerator il = methodBuilder.GetILGenerator();
                    #region  面的il相当于
                    //下面的il相当于
                    //public class parent
                    //{
                    //    public virtual string test(List<string> p1, int p2)
                    //    {
                    //        return "123";
                    //    }
                    //}
                    //public class child : parent
                    //{
                    //    public override string test(List<string> p1, int p2)
                    //    {
                    //        object[] Parameter = new object[2];
                    //        Parameter[0] = p1;
                    //        Parameter[1] = p2;
                    //        Func<List<string>, int, string> DelegateMethod = base.test;

                    //        Invocation invocation = new Invocation();
                    //        invocation.Parameter = Parameter;
                    //        invocation.DelegateMethod = DelegateMethod;
                    //        Interceptor interceptor = new Interceptor();
                    //        return (string)interceptor.Intercept(invocation);
                    //    }
                    //}
                    #endregion
                    Label label1 = il.DefineLabel();

                    il.DeclareLocal(typeof(object[]));
                    il.DeclareLocal(delegateType);
                    il.DeclareLocal(typeof(Invocation));
                    il.DeclareLocal(interceptorType);
                    LocalBuilder re = null;
                    if (returnType != typeof(void))
                    {
                        re = il.DeclareLocal(returnType);
                    }
                    il.Emit(OpCodes.Ldc_I4, paramType.Length);
                    il.Emit(OpCodes.Newarr, typeof(object));
                    il.Emit(OpCodes.Stloc, 0);
                    for (var i = 0; i < paramType.Length; i++)
                    {
                        il.Emit(OpCodes.Ldloc, 0);
                        il.Emit(OpCodes.Ldc_I4, i);
                        il.Emit(OpCodes.Ldarg, i + 1);
                        if (paramType[i].IsValueType)
                        {
                            il.Emit(OpCodes.Box, paramType[i]);
                        }
                        il.Emit(OpCodes.Stelem_Ref);
                    }
                    il.Emit(OpCodes.Ldarg, 0);
                    il.Emit(OpCodes.Ldftn, targetMethod);
                    il.Emit(OpCodes.Newobj, delegateType.GetConstructors()[0]);
                    il.Emit(OpCodes.Stloc, 1);
                    il.Emit(OpCodes.Newobj, typeof(Invocation).GetConstructors(BindingFlags.Public | BindingFlags.Instance).First(e => e.GetParameters().Length == 0));
                    il.Emit(OpCodes.Stloc, 2);
                    il.Emit(OpCodes.Ldloc, 2);
                    il.Emit(OpCodes.Ldloc, 0);
                    il.Emit(OpCodes.Callvirt, typeof(Invocation).GetMethod("set_Parameter"));
                    il.Emit(OpCodes.Ldloc, 2);
                    il.Emit(OpCodes.Ldloc, 1);
                    il.Emit(OpCodes.Callvirt, typeof(Invocation).GetMethod("set_DelegateMethod"));
                    il.Emit(OpCodes.Newobj, interceptorType.GetConstructors(BindingFlags.Public | BindingFlags.Instance).First(e => e.GetParameters().Length == 0));
                    il.Emit(OpCodes.Stloc, 3);
                    il.Emit(OpCodes.Ldloc, 3);
                    il.Emit(OpCodes.Ldloc, 2);
                    il.Emit(OpCodes.Callvirt, interceptorType.GetMethod("Intercept"));
                    if (returnType != typeof(void))
                    {
                        il.Emit(OpCodes.Castclass, returnType);
                        il.Emit(OpCodes.Stloc_S, re);
                        il.Emit(OpCodes.Br_S, label1);
                        il.MarkLabel(label1);
                        il.Emit(OpCodes.Ldloc_S, re);
                    }
                    else
                    {
                        il.Emit(OpCodes.Pop);
                    }
                    il.Emit(OpCodes.Ret);
                }
            }
            //真正创建,并返回
            Type proxyType = typeBuilder.CreateTypeInfo();
            return(proxyType);
        }