/// <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); } } } }
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); }
internal _Visitor(FluentMethodBuilder method) { _method = method; }