PageRenderTime 103ms CodeModel.GetById 60ms app.highlight 8ms RepoModel.GetById 33ms app.codeStats 0ms

/src/LinFu.Reflection.Emit/MethodDefinitionExtensions.cs

http://github.com/philiplaureano/LinFu
C# | 187 lines | 87 code | 26 blank | 74 comment | 15 complexity | 65670494888063036dfaeb11468d9aaa MD5 | raw file
  1using System;
  2using System.Linq;
  3using Mono.Cecil;
  4using Mono.Cecil.Cil;
  5
  6namespace LinFu.Reflection.Emit
  7{
  8    /// <summary>
  9    ///     A class that extends the <see cref="MethodDefinition" />
 10    ///     class with features similar to the features in the
 11    ///     System.Reflection.Emit namespace.
 12    /// </summary>
 13    public static class MethodDefinitionExtensions
 14    {
 15        /// <summary>
 16        ///     Returns the <see cref="ILProcessor" /> instance
 17        ///     associated with the body of the <paramref name="method">target method</paramref>.
 18        /// </summary>
 19        /// <param name="method">The target method to be modified.</param>
 20        /// <returns>The <see cref="ILProcessor" /> instance that points to the instructions of the method body.</returns>
 21        public static ILProcessor GetILGenerator(this MethodDefinition method)
 22        {
 23            return method.Body.GetILProcessor();
 24        }
 25
 26        /// <summary>
 27        ///     Adds a <see cref="VariableDefinition">local variable</see>
 28        ///     instance to the target <paramref name="methodDef">method definition</paramref>.
 29        /// </summary>
 30        /// <param name="methodDef">The <paramref name="methodDef" /> instance which will contain the local variable.</param>
 31        /// <param name="localType">
 32        ///     The object <see cref="System.Type">type</see> that describes the type of objects that will be
 33        ///     stored by the local variable.
 34        /// </param>
 35        /// <returns>A <see cref="VariableDefinition" /> that represents the local variable itself.</returns>
 36        public static VariableDefinition AddLocal(this MethodDefinition methodDef, Type localType)
 37        {
 38            var declaringType = methodDef.DeclaringType;
 39            var module = declaringType.Module;
 40            var variableType = module.Import(localType);
 41            var result = new VariableDefinition(variableType);
 42
 43            methodDef.Body.Variables.Add(result);
 44
 45            return result;
 46        }
 47
 48        /// <summary>
 49        ///     Adds a named <see cref="VariableDefinition">local variable</see>
 50        ///     instance to the target <paramref name="method">method definition</paramref>.
 51        /// </summary>
 52        /// <param name="method">The <paramref name="method" /> instance which will contain the local variable.</param>
 53        /// <param name="variableName">The name of the local variable.</param>
 54        /// <param name="variableType">
 55        ///     The object <see cref="System.Type">type</see> that describes the type of objects that will
 56        ///     be stored by the local variable.
 57        /// </param>
 58        /// <returns></returns>
 59        public static VariableDefinition AddLocal(this MethodDefinition method, string variableName, Type variableType)
 60        {
 61            var module = method.DeclaringType.Module;
 62            var localType = module.Import(variableType);
 63
 64            VariableDefinition newLocal = null;
 65            foreach (VariableDefinition local in method.Body.Variables)
 66            {
 67                // Match the variable name and type
 68                if (local.Name != variableName || local.VariableType != localType)
 69                    continue;
 70
 71                newLocal = local;
 72            }
 73
 74            // If necessary, create the local variable
 75            if (newLocal == null)
 76            {
 77                var body = method.Body;
 78                newLocal = new VariableDefinition(variableName, localType);
 79
 80                body.Variables.Add(newLocal);
 81            }
 82
 83            return newLocal;
 84        }
 85
 86        /// <summary>
 87        ///     Adds a set of parameter types to the target <paramref name="method" />.
 88        /// </summary>
 89        /// <param name="method">The target method.</param>
 90        /// <param name="parameterTypes">The list of types that describe the method signature.</param>
 91        public static void AddParameters(this MethodDefinition method, Type[] parameterTypes)
 92        {
 93            var declaringType = method.DeclaringType;
 94            var module = declaringType.Module;
 95
 96            // Build the parameter list
 97            foreach (var type in parameterTypes)
 98            {
 99                TypeReference parameterType;
100                var isGeneric = type.ContainsGenericParameters && type.IsGenericType;
101                var hasGenericParameter = type.HasElementType && type.GetElementType().IsGenericParameter;
102                var shouldImportMethodContext = isGeneric || type.IsGenericParameter || hasGenericParameter;
103
104                parameterType = shouldImportMethodContext ? module.Import(type, method) : module.Import(type);
105
106                var param = new ParameterDefinition(parameterType);
107                method.Parameters.Add(param);
108            }
109        }
110
111
112        /// <summary>
113        ///     Assigns the <paramref name="returnType" /> for the target method.
114        /// </summary>
115        /// <param name="method">The target method.</param>
116        /// <param name="returnType">The <see cref="System.Type" /> instance that describes the return type.</param>
117        public static void SetReturnType(this MethodDefinition method, Type returnType)
118        {
119            var declaringType = method.DeclaringType;
120            var module = declaringType.Module;
121
122            TypeReference actualReturnType;
123
124            if (returnType.ContainsGenericParameters && returnType.IsGenericType || returnType.IsGenericParameter)
125                actualReturnType = module.Import(returnType, method);
126            else
127                actualReturnType = module.Import(returnType);
128
129            method.ReturnType = actualReturnType;
130        }
131
132
133        /// <summary>
134        ///     Adds a generic parameter type to the <paramref name="method" />.
135        /// </summary>
136        /// <param name="method">The target method.</param>
137        /// <param name="parameterType">The parameter type.</param>
138        /// <returns>A <see cref="TypeReference" /> that represents the generic parameter type.</returns>
139        public static TypeReference AddGenericParameter(this MethodDefinition method, Type parameterType)
140        {
141            // Check if the parameter type already exists
142            var matches = (from GenericParameter p in method.GenericParameters
143                where p.Name == parameterType.Name
144                select p).ToList();
145
146            // Reuse the existing parameter
147            if (matches.Count > 0)
148                return matches[0];
149
150            var parameter = new GenericParameter(parameterType.Name, method);
151            method.GenericParameters.Add(parameter);
152
153            return parameter;
154        }
155
156        /// <summary>
157        ///     Adds a <see cref="VariableDefinition">local variable</see>
158        ///     instance to the target <paramref name="methodDef">method definition</paramref>.
159        /// </summary>
160        /// <typeparam name="T">
161        ///     The object <see cref="System.Type">type</see> that describes the type of objects that will be
162        ///     stored by the local variable.
163        /// </typeparam>
164        /// <param name="methodDef">The <paramref name="methodDef" /> instance which will contain the local variable.</param>
165        /// <returns>A <see cref="VariableDefinition" /> that represents the local variable itself.</returns>
166        public static VariableDefinition AddLocal<T>(this MethodDefinition methodDef)
167        {
168            return methodDef.AddLocal(typeof(T));
169        }
170
171        /// <summary>
172        ///     Adds a named <see cref="VariableDefinition">local variable</see>
173        ///     instance to the target <paramref name="methodDef">method definition</paramref>.
174        /// </summary>
175        /// <typeparam name="T">
176        ///     The object <see cref="System.Type">type</see> that describes the type of objects that will be
177        ///     stored by the local variable.
178        /// </typeparam>
179        /// <param name="methodDef">The <paramref name="methodDef" /> instance which will contain the local variable.</param>
180        /// <param name="variableName">The name of the local variable.</param>
181        /// <returns>A <see cref="VariableDefinition" /> that represents the local variable itself.</returns>
182        public static VariableDefinition AddLocal<T>(this MethodDefinition methodDef, string variableName)
183        {
184            return methodDef.AddLocal(variableName, typeof(T));
185        }
186    }
187}