/// <summary> /// Adds a new method to the class, with the given name and method signature. /// </summary> /// <param name="name">The name of the method. name cannot contain embedded nulls. </param> /// <param name="methodInfoDeclaration">The method whose declaration is to be used.</param> /// <param name="attributes">The attributes of the method. </param> /// <returns>The defined method.</returns> public MethodBuilderHelper DefineMethod( string name, MethodInfo methodInfoDeclaration, MethodAttributes attributes) { if (methodInfoDeclaration == null) throw new ArgumentNullException("methodInfoDeclaration"); MethodBuilderHelper method; ParameterInfo[] pi = methodInfoDeclaration.GetParameters(); Type[] parameters = new Type[pi.Length]; // When a method contains a generic parameter we need to replace all // generic types from methodInfoDeclaration with local ones. // if (methodInfoDeclaration.ContainsGenericParameters) { method = new MethodBuilderHelper(this, _typeBuilder.DefineMethod(name, attributes, methodInfoDeclaration.CallingConvention), false); Type[] genArgs = methodInfoDeclaration.GetGenericArguments(); GenericTypeParameterBuilder[] genParams = method.MethodBuilder.DefineGenericParameters( Array.ConvertAll<Type, string>(genArgs, delegate (Type t) { return t.Name; })); // Copy parameter constraints. // List<Type> interfaceConstraints = null; for (int i = 0; i < genParams.Length; i++) { genParams[i].SetGenericParameterAttributes(genArgs[i].GenericParameterAttributes); foreach (Type constraint in genArgs[i].GetGenericParameterConstraints()) { if (constraint.IsClass) genParams[i].SetBaseTypeConstraint(constraint); else { if (interfaceConstraints == null) interfaceConstraints = new List<Type>(); interfaceConstraints.Add(constraint); } } if (interfaceConstraints != null && interfaceConstraints.Count > 0) { genParams[i].SetInterfaceConstraints(interfaceConstraints.ToArray()); interfaceConstraints.Clear(); } } for (int i = 0; i < pi.Length; i++) parameters[i] = TypeHelper.TranslateGenericParameters(pi[i].ParameterType, genParams); method.MethodBuilder.SetParameters(parameters); method.MethodBuilder.SetReturnType(TypeHelper.TranslateGenericParameters( methodInfoDeclaration.ReturnType, genParams)); // Now its safe to add a custom attribute. // method.MethodBuilder.SetCustomAttribute(method.Type.Assembly.BLToolkitAttribute); } else { for (int i = 0; i < pi.Length; i++) parameters[i] = pi[i].ParameterType; method = DefineMethod( name, attributes, methodInfoDeclaration.CallingConvention, methodInfoDeclaration.ReturnType, parameters); } // Compiler overrides methods only for interfaces. We do the same. // If we wanted to override virtual methods, then methods should've had // MethodAttributes.VtableLayoutMask attribute // and the following condition should've been used below: // if ((methodInfoDeclaration is FakeMethodInfo) == false) // if (methodInfoDeclaration.DeclaringType.IsInterface && !(methodInfoDeclaration is FakeMethodInfo)) { OverridenMethods.Add(methodInfoDeclaration, method.MethodBuilder); _typeBuilder.DefineMethodOverride(method.MethodBuilder, methodInfoDeclaration); } method.OverriddenMethod = methodInfoDeclaration; for (int i = 0; i < pi.Length; i++) method.MethodBuilder.DefineParameter(i + 1, pi[i].Attributes, pi[i].Name); return method; }
/// <summary> /// Adds a new method to the class, with the given name and method signature. /// </summary> /// <param name="name">The name of the method. name cannot contain embedded nulls. </param> /// <param name="methodInfoDeclaration">The method whose declaration is to be used.</param> /// <param name="attributes">The attributes of the method. </param> /// <returns>The defined method.</returns> public MethodBuilderHelper DefineMethod( string name, MethodInfo methodInfoDeclaration, MethodAttributes attributes) { if (methodInfoDeclaration == null) { throw new ArgumentNullException("methodInfoDeclaration"); } MethodBuilderHelper method; ParameterInfo[] pi = methodInfoDeclaration.GetParameters(); Type[] parameters = new Type[pi.Length]; // When a method contains a generic parameter we need to replace all // generic types from methodInfoDeclaration with local ones. // if (methodInfoDeclaration.ContainsGenericParameters) { method = new MethodBuilderHelper(this, _typeBuilder.DefineMethod(name, attributes, methodInfoDeclaration.CallingConvention), false); Type[] genArgs = methodInfoDeclaration.GetGenericArguments(); GenericTypeParameterBuilder[] genParams = method.MethodBuilder.DefineGenericParameters( Array.ConvertAll <Type, string>(genArgs, delegate(Type t) { return(t.Name); })); // Copy parameter constraints. // List <Type> interfaceConstraints = null; for (int i = 0; i < genParams.Length; i++) { genParams[i].SetGenericParameterAttributes(genArgs[i].GenericParameterAttributes); foreach (Type constraint in genArgs[i].GetGenericParameterConstraints()) { if (constraint.IsClass) { genParams[i].SetBaseTypeConstraint(constraint); } else { if (interfaceConstraints == null) { interfaceConstraints = new List <Type>(); } interfaceConstraints.Add(constraint); } } if (interfaceConstraints != null && interfaceConstraints.Count > 0) { genParams[i].SetInterfaceConstraints(interfaceConstraints.ToArray()); interfaceConstraints.Clear(); } } for (int i = 0; i < pi.Length; i++) { parameters[i] = TypeHelper.TranslateGenericParameters(pi[i].ParameterType, genParams); } method.MethodBuilder.SetParameters(parameters); method.MethodBuilder.SetReturnType(TypeHelper.TranslateGenericParameters( methodInfoDeclaration.ReturnType, genParams)); // Now its safe to add a custom attribute. // method.MethodBuilder.SetCustomAttribute(method.Type.Assembly.BLToolkitAttribute); } else { for (int i = 0; i < pi.Length; i++) { parameters[i] = pi[i].ParameterType; } method = DefineMethod( name, attributes, methodInfoDeclaration.CallingConvention, methodInfoDeclaration.ReturnType, parameters); } // Compiler overrides methods only for interfaces. We do the same. // If we wanted to override virtual methods, then methods should've had // MethodAttributes.VtableLayoutMask attribute // and the following condition should've been used below: // if ((methodInfoDeclaration is FakeMethodInfo) == false) // if (methodInfoDeclaration.DeclaringType.IsInterface && !(methodInfoDeclaration is FakeMethodInfo)) { OverridenMethods.Add(methodInfoDeclaration, method.MethodBuilder); _typeBuilder.DefineMethodOverride(method.MethodBuilder, methodInfoDeclaration); } method.OverriddenMethod = methodInfoDeclaration; for (int i = 0; i < pi.Length; i++) { method.MethodBuilder.DefineParameter(i + 1, pi[i].Attributes, pi[i].Name); } return(method); }