// 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"); } }
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; } } }
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); } } }
/// <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); }
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); }
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"); }
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); }
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); }
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(); }
/// <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); } }
/// <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); }
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); }
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); } } }
/// <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); }