/// <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;
		}
Exemple #2
0
        /// <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);
        }