Example #1
0
        /// <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);
        }