/// <summary>
        /// Creates a method that matches the signature defined in the
        /// <paramref name="method"/> parameter.
        /// </summary>
        /// <param name="targetType">The type that will host the new method.</param>
        /// <param name="method">The method from which the signature will be derived.</param>
        public virtual MethodDefinition CreateMethod(TypeDefinition targetType, MethodInfo method)
        {
            #region Match the method signature

            ModuleDefinition module = targetType.Module;
            string methodName = method.Name;

            // If the method is a member defined on an interface type,
            // we need to rename the method to avoid
            // any naming conflicts in the type itself
            if (method.DeclaringType.IsInterface)
            {
                string parentName = method.DeclaringType.FullName;

                // Rename the parent type to its fully qualified name
                // if it is a generic type
                methodName = string.Format("{0}.{1}", parentName, methodName);
            }

            MethodAttributes baseAttributes = MethodAttributes.Virtual |
                                              MethodAttributes.HideBySig;

            MethodAttributes attributes = default(MethodAttributes);

            #region Match the visibility of the target method

            if (method.IsFamilyOrAssembly)
                attributes = baseAttributes | MethodAttributes.FamORAssem;

            if (method.IsFamilyAndAssembly)
                attributes = baseAttributes | MethodAttributes.FamANDAssem;

            if (method.IsPublic)
                attributes = baseAttributes | MethodAttributes.Public;

            #endregion

            // Build the list of parameter types
            Type[] parameterTypes = (from param in method.GetParameters()
                                     let type = param.ParameterType
                                     let importedType = type
                                     select importedType).ToArray();

            //Build the list of generic parameter types
            Type[] genericParameterTypes = method.GetGenericArguments();

            MethodDefinition newMethod = targetType.DefineMethod(methodName, attributes,
                                                                 method.ReturnType, parameterTypes,
                                                                 genericParameterTypes);

            newMethod.Body.InitLocals = true;
            newMethod.ImplAttributes = MethodImplAttributes.IL | MethodImplAttributes.Managed;
            newMethod.HasThis = true;

            // Match the generic type arguments
            Type[] typeArguments = method.GetGenericArguments();

            if (typeArguments != null || typeArguments.Length > 0)
                MatchGenericArguments(newMethod, typeArguments);

            MethodReference originalMethodRef = module.Import(method);
            newMethod.Overrides.Add(originalMethodRef);

            #endregion

            // Define the method body
            if (Emitter != null)
                Emitter.Emit(method, newMethod);

            return newMethod;
        }
Esempio n. 2
0
        /// <summary>
        /// Defines the factory method on the singleton type.
        /// </summary>
        /// <param name="singletonType">The singleton type that will be generated by the emitter.</param>
        /// <param name="il">The <see cref="ILProcessor"/> instance that points to the target method body.</param>
        /// <param name="instanceField">The static field that holds the singleton instance.</param>
        /// <returns>The singleton type's GetInstance method.</returns>
        private MethodDefinition DefineGetInstance(TypeDefinition singletonType, ILProcessor il, FieldDefinition instanceField)
        {
            // Define the GetInstance method on the singleton type
            var getInstanceMethodAttributes = MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.HideBySig;
            var getInstanceMethod = singletonType.DefineMethod("GetInstance", getInstanceMethodAttributes, typeof(object), new System.Type[0], new System.Type[0]);
            var singletonWorker = getInstanceMethod.GetILGenerator();

            singletonWorker.Emit(OpCodes.Ldsfld, instanceField);
            singletonWorker.Emit(OpCodes.Ret);

            return getInstanceMethod;
        }