/// <summary> /// Emits the IL for this method. Adds a backing static method to which the expression is compiled, /// then calls that method with appropriate arguments /// </summary> /// <param name="il">IL generator for the current method</param> /// <param name="sourceField">Field representing the source component</param> /// <param name="typeBeingBuilt">The type being built</param> internal override void Emit(ILGenerator il, FieldBuilder sourceField, TypeSpecifier typeBeingBuilt) { var pTypes = _expr.Parameters.Select(p => p.Type).ToArray(); var nestedClass = typeBeingBuilt.CreateDisplayClass(); var lambda = nestedClass.TypeBuilder.DefineMethod(nestedClass.GetMethodName(_name), MethodAttributes.Static | MethodAttributes.HideBySig | MethodAttributes.Public, _expr.ReturnType, pTypes); // We'd really like to compile this straight into our method, // but `LambdaExpression.CompileToMethod` only takes static methods, // so the next best thing is to use this attribute to tell the JITter // that it should be inlined. lambda.SetCustomAttribute(new CustomAttributeBuilder( typeof(MethodImplAttribute).GetConstructor(new Type[] { typeof(MethodImplOptions) }), new object[1] { MethodImplOptions.AggressiveInlining })); _expr.CompileToMethod(lambda); foreach (var p in _params) { p.Emit(il, sourceField, typeBeingBuilt.TypeBuilder); } il.Emit(OpCodes.Call, lambda); il.Emit(OpCodes.Ret); }
/// <summary> /// Emits the IL for this method /// </summary> /// <param name="il">IL Generator</param> /// <param name="sourceField">The field containing the source component</param> /// <param name="typeBeingBuilt">The type being built</param> internal override void Emit(ILGenerator il, FieldBuilder sourceField, TypeSpecifier typeBeingBuilt) { var nestedType = typeBeingBuilt.CreateDisplayClass(); var backingField = nestedType.TypeBuilder.DefineField(nestedType.GetInvokeName(_name), _invoke.GetType(), FieldAttributes.Static | FieldAttributes.Public); typeBeingBuilt.RunAfterCreation(() => { backingField.SafeSetValue(null, _invoke); }); il.Emit(OpCodes.Ldsfld, backingField); foreach (var p in _params) { p.Emit(il, sourceField, typeBeingBuilt.TypeBuilder); } il.Emit(OpCodes.Callvirt, _invoke.GetType().GetMethod("Invoke")); il.Emit(OpCodes.Ret); }