/// <summary>
        /// Creates a new FluentMethodBuilder that has the interface of an Action.
        /// That is: It does not receive any parameters and does not return values.
        /// </summary>
        public static FluentMethodBuilder CreateAction()
        {
            var result = new FluentMethodBuilder(typeof(void));

            result.MakeParametersReadOnly();
            return(result);
        }
        private static void _GeneratePosCall(FluentMethodBuilder method, Type[] originalParameterTypes, ILGenerator methodGenerator, int count, List <LocalBuilder> locals, Type[] parameterTypesForDelegate)
        {
            int localIndex = -1;

            for (int i = 0; i < count; i++)
            {
                int realIndex;
                if (method.IsStatic)
                {
                    realIndex = i;
                }
                else
                {
                    realIndex = i - 1;
                }

                if (realIndex >= 0)
                {
                    var originalParameterType = originalParameterTypes[realIndex];
                    var parameterType         = parameterTypesForDelegate[realIndex];
                    if (originalParameterType != parameterType && parameterType.IsGenericType && parameterType.GetGenericTypeDefinition() == typeof(FluentMethodBuilder.Box <>))
                    {
                        localIndex++;
                        var local = locals[localIndex];
                        methodGenerator.Emit(OpCodes.Ldarg, i);

                        methodGenerator.Emit(OpCodes.Ldloc, local);
                        methodGenerator.Emit(OpCodes.Ldfld, parameterType.GetField("Value"));

                        methodGenerator.Emit(OpCodes.Stobj, originalParameterType);
                    }
                }
            }
        }
Exemple #3
0
        private Expression _RebuildArguments(FluentMethodBuilder method, Expression expression)
        {
            if (method.IsStatic)
            {
                return(expression);
            }

            if (_method.IsStatic)
            {
                throw new InvalidOperationException("A static method is trying to call a non-static method without giving the instance.");
            }

            var resultExpression =
                Expression.Call(_addInstanceMethod, _method.TypeBuilder.ThisExpression, expression);

            return(resultExpression);
        }
        private static void _GeneratePreCall(FluentMethodBuilder method, Type[] originalParameterTypes, ILGenerator methodGenerator, int count, List <LocalBuilder> locals, Type[] parameterTypesForDelegate)
        {
            for (int i = 0; i < count; i++)
            {
                int realIndex;
                if (method.IsStatic)
                {
                    realIndex = i;
                }
                else
                {
                    realIndex = i - 1;
                }

                if (realIndex >= 0)
                {
                    var originalParameterType = originalParameterTypes[realIndex];
                    var parameterType         = parameterTypesForDelegate[realIndex];
                    if (originalParameterType != parameterType && parameterType.IsGenericType && parameterType.GetGenericTypeDefinition() == typeof(FluentMethodBuilder.Box <>))
                    {
                        var local = methodGenerator.DeclareLocal(parameterType);
                        locals.Add(local);
                        methodGenerator.Emit(OpCodes.Newobj, parameterType.GetConstructor(Type.EmptyTypes));
                        methodGenerator.Emit(OpCodes.Stloc, local);
                        methodGenerator.Emit(OpCodes.Ldloc, local);
                        methodGenerator.Emit(OpCodes.Ldarg, i);
                        methodGenerator.Emit(OpCodes.Ldobj, originalParameterType);
                        methodGenerator.Emit(OpCodes.Stfld, parameterType.GetField("Value"));
                        methodGenerator.Emit(OpCodes.Ldloc, local);
                    }
                    else
                    {
                        methodGenerator.Emit(OpCodes.Ldarg, i);
                    }
                }
                else
                {
                    methodGenerator.Emit(OpCodes.Ldarg_0);
                }
            }
        }
        /// <summary>
        /// Adds a method to this type.
        /// </summary>
        /// <typeparam name="T">The type of the result this method will generate.</typeparam>
        public FluentMethodBuilder <T> AddMethod <T>(string name, bool isStatic = false, bool respectVisibility = false)
        {
            if (name == null)
            {
                throw new ArgumentNullException("name");
            }

            _CheckUncompiled();

            var result = new FluentMethodBuilder <T>(this, name, isStatic, _creatorThreadId, _methods.Count, respectVisibility);

            result.AddExternal(_delegatesExpression);

            if (!isStatic)
            {
                result.AddParameter(_thisVariable);
            }

            _methods.Add(result);
            return(result);
        }
        private MethodBuilder _Compile(FluentMethodBuilder method, int index)
        {
            var compiledMethodType = method._Precompile();

            MethodAttributes methodAttributes = MethodAttributes.Public;

            if (method.IsStatic)
            {
                methodAttributes |= MethodAttributes.Static;
            }
            else
            {
                methodAttributes |= MethodAttributes.Virtual;
            }

            // the originalParameterTypes don't include a Box<> or ByRef because
            // they come from a field.
            Type[] originalParameterTypes;

            // the parameterTypesForDelegate may have Box<> types.
            Type[] parameterTypesForDelegate;

            // the parameterTypesForGeneratedMethod will replace Box<> parameter by ref parameters.
            Type[] parameterTypesForGeneratedMethod;

            int parameterCount = method._parameters.Count;
            int parameterIndex = -1;

            using (var enumerator = method._parameters.GetEnumerator())
            {
                if (!method.IsStatic)
                {
                    parameterCount--;
                    enumerator.MoveNext();
                }

                originalParameterTypes           = new Type[parameterCount];
                parameterTypesForDelegate        = new Type[parameterCount];
                parameterTypesForGeneratedMethod = new Type[parameterCount];

                while (enumerator.MoveNext())
                {
                    parameterIndex++;
                    var pair = enumerator.Current;
                    var fieldInfoAndSourcePair = pair.Key;
                    var parameterExpression    = pair.Value;

                    var fieldType     = fieldInfoAndSourcePair.Key.FieldType;
                    var parameterType = parameterExpression.Type;
                    originalParameterTypes[parameterIndex]    = fieldType;
                    parameterTypesForDelegate[parameterIndex] = parameterType;

                    var parameterTypeForGeneratedMethod = fieldType;
                    if (parameterExpression.IsByRef || fieldType != parameterType)
                    {
                        parameterTypeForGeneratedMethod = fieldType.MakeByRefType();
                    }

                    parameterTypesForGeneratedMethod[parameterIndex] = parameterTypeForGeneratedMethod;
                }
            }

            var methodBuilder = _type.DefineMethod(method.Name, methodAttributes, method.ReturnType, parameterTypesForGeneratedMethod);

            foreach (var interfaceType in _interfaceTypes)
            {
                var methodToOverride = interfaceType.GetMethod(method.Name, originalParameterTypes);
                if (methodToOverride != null)
                {
                    _type.DefineMethodOverride(methodBuilder, methodToOverride);
                }
            }

            var methodGenerator = methodBuilder.GetILGenerator();

            int count = originalParameterTypes.Length;

            if (!method.IsStatic)
            {
                count++;
            }

            if (method._respectVisibility)
            {
                if (method.IsStatic)
                {
                    method._Compile(null, methodBuilder);
                }
                else
                {
                    var allParameterTypes = new Type[parameterTypesForGeneratedMethod.Length + 1];
                    allParameterTypes[0] = _type;
                    parameterTypesForGeneratedMethod.CopyTo(allParameterTypes, 1);

                    var otherMethod = _type.DefineMethod("." + method._delegateIndex, MethodAttributes.Static, method.ReturnType, allParameterTypes);
                    method._Compile(null, otherMethod);
                    _EmitDirectCall(methodBuilder, otherMethod, allParameterTypes.Length);
                }
            }
            else
            {
                methodGenerator.Emit(OpCodes.Ldsfld, _delegatesField);
                methodGenerator.Emit(OpCodes.Ldc_I4, index);
                methodGenerator.Emit(OpCodes.Ldelem, compiledMethodType);

                var locals = new List <LocalBuilder>();
                _GeneratePreCall(method, originalParameterTypes, methodGenerator, count, locals, parameterTypesForDelegate);

                methodGenerator.Emit(OpCodes.Callvirt, compiledMethodType.GetMethod("Invoke"));

                if (locals.Count > 0)
                {
                    _GeneratePosCall(method, originalParameterTypes, methodGenerator, count, locals, parameterTypesForDelegate);
                }

                methodGenerator.Emit(OpCodes.Ret);
            }

            return(methodBuilder);
        }
Exemple #7
0
 internal _Visitor(FluentMethodBuilder method)
 {
     _method = method;
 }