Exemplo n.º 1
0
        public static TInterface Implement <TInterface>(ILibrary library, Func <string, string> lookupFunctionName = null)
            where TInterface : class
        {
            if (library == null)
            {
                throw new ArgumentNullException("library");
            }

            var mapper = new LibraryInterfaceMapper(new DelegateTypeBuilder(),
                                                    new DefaultConstructorBuilder(lookupFunctionName),
                                                    new DefaultMethodCallWrapper());

            return(mapper.Implement <TInterface>(library));
        }
Exemplo n.º 2
0
        public static TInterface Implement <TInterface>(ILibrary library, IMethodCallProbe <TInterface> probe, Func <string, string> lookupFunctionName = null)
            where TInterface : class
        {
            if (library == null)
            {
                throw new ArgumentNullException("library");
            }
            if (probe == null)
            {
                throw new ArgumentNullException("probe");
            }

            var constructorBuilder = new ProbingConstructorBuilder(lookupFunctionName);
            var methoCallWrapper   = new ProbingMethodCallWrapper(() => constructorBuilder.ProbeField);
            var mapper             = new LibraryInterfaceMapper(new DelegateTypeBuilder(), constructorBuilder, methoCallWrapper);

            return(mapper.Implement <TInterface>(library, probe));
        }
Exemplo n.º 3
0
        /// <summary>
        /// Creates a <see cref="MethodBuilder"/> and implements a default wrapper.
        /// </summary>
        /// <param name="owner">The type that will own this method.</param>
        /// <param name="interfaceType">Type of interface implemented by the <paramref name="owner"/>.</param>
        /// <param name="overrideMethod">Method to override.</param>
        /// <param name="fieldBuilders">Fields specified by the <see paramref="owner"/>.</param>
        /// <returns>MethodBuilder with an already implemented wrapper.</returns>
        public MethodBuilder GenerateInvocation(TypeBuilder owner, Type interfaceType, MethodInfo overrideMethod, IEnumerable <FieldBuilder> fieldBuilders)
        {
            var result = owner.DefineMethod
                         (
                overrideMethod.Name,
                MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.Final |
                MethodAttributes.HideBySig | MethodAttributes.NewSlot,
                overrideMethod.ReturnType,
                overrideMethod.GetParameters().OrderBy(p => p.Position).Select(t => t.ParameterType).ToArray()
                         );

            result.SetImplementationFlags(MethodImplAttributes.AggressiveInlining);

            var generator  = result.GetILGenerator();
            var fieldName  = LibraryInterfaceMapper.GetFieldNameForMethodInfo(overrideMethod);
            var field      = fieldBuilders.First(f => f.Name == fieldName);
            var parameters = overrideMethod.GetParameters();

            OnInvokeBegin(owner, interfaceType, generator, overrideMethod);
            generator.Emit(OpCodes.Ldarg_0);      //  this
            generator.Emit(OpCodes.Ldfld, field); // MethodNameProc _glMethodName. Initialized by constructor.
            foreach (var item in parameters.Where(p => !p.IsRetval).Select((p, i) => new { Type = p, Index = i }))
            {
                generator.Emit(OpCodes.Ldarg, item.Index + 1);
            }

            generator.EmitCall(OpCodes.Callvirt, field.FieldType.GetMethod("Invoke"), null);

            OnInvokeEnd(owner, interfaceType, generator, overrideMethod);

            generator.Emit(OpCodes.Ret);

            owner.DefineMethodOverride(result, overrideMethod);

            return(result);
        }
        /// <summary>
        /// Generates the constructor using the specified arguments.
        /// </summary>
        /// <param name="owner"></param>
        /// <param name="interfaceType"></param>
        /// <param name="methods"></param>
        /// <param name="fields"></param>
        /// <returns></returns>
        public ConstructorBuilder GenerateConstructor(TypeBuilder owner, Type interfaceType, IEnumerable <MethodInfo> methods, IEnumerable <FieldBuilder> fields)
        {
            var builder = DefineConstructor(owner, interfaceType);

            var generator = builder.GetILGenerator();

            var notSupportedConstructor = typeof(MissingEntryPointException).GetConstructor(
                new[] { typeof(string), typeof(ILibrary) });

            if (notSupportedConstructor == null)
            {
                throw new MissingMethodException("MissingEntryPointException", ".ctr(string, ILibrary)");
            }
            var loc           = generator.DeclareLocal(typeof(Delegate));
            var fieldBuilders = fields as FieldBuilder[] ?? fields.ToArray();

            EmitBegin(owner, interfaceType, generator);

            foreach (var method in methods)
            {
                generator.BeginScope();

                var entryPoint = method.GetCustomAttributes(typeof(EntryPointAttribute), false).OfType <EntryPointAttribute>().FirstOrDefault();

                string methodName;
                if (entryPoint != null)
                {
                    methodName = entryPoint.Name;
                }
                else if (lookupFunctionName != null)
                {
                    methodName = lookupFunctionName(method.Name);
                }
                else
                {
                    var libAttrib = interfaceType.GetCustomAttributes(typeof(EntryPointFormatAttribute), false).OfType <EntryPointFormatAttribute>().FirstOrDefault();
                    if (libAttrib != null && !string.IsNullOrEmpty(libAttrib.Format))
                    {
                        methodName = string.Format(libAttrib.Format, method.Name);
                    }
                    else
                    {
                        methodName = method.Name;
                    }
                }

                var name    = LibraryInterfaceMapper.GetFieldNameForMethodInfo(method);
                var field   = fieldBuilders.Single(f => f.Name == name);
                var okLabel = generator.DefineLabel();

                generator.Emit(OpCodes.Ldarg_1);                                                                                         // ILibrary
                generator.Emit(OpCodes.Ldstr, methodName);                                                                               // load constant method name

                var getMethod = typeof(ILibrary).GetMethod("GetProcedure", new[] { typeof(string) }).MakeGenericMethod(field.FieldType); // lib.GetProcedure<Field.FieldType>(methodName)
                generator.EmitCall(OpCodes.Callvirt, getMethod, null);

                generator.Emit(OpCodes.Stloc, loc); // result = GetProcedure<DelegateType>(methodName);

                // if result == null throw MethodNotSupportedException
                generator.Emit(OpCodes.Ldloc, loc);
                generator.Emit(OpCodes.Brtrue_S, okLabel); // if(result != null) goto okLabel
                generator.Emit(OpCodes.Ldstr, methodName);
                generator.Emit(OpCodes.Ldarg_1);
                generator.Emit(OpCodes.Newobj, notSupportedConstructor);
                generator.Emit(OpCodes.Throw); // throw new MissingMethodException(methodName)

                generator.MarkLabel(okLabel);
                // Everything went okay. Set the delegate to the returned function.
                generator.Emit(OpCodes.Ldarg_0);      // this
                generator.Emit(OpCodes.Ldloc, loc);   // result
                generator.Emit(OpCodes.Stfld, field); // this._fieldName = result;

                generator.EndScope();
            }

            EmitEnd(owner, interfaceType, generator);

            generator.Emit(OpCodes.Ret);

            return(builder);
        }
Exemplo n.º 5
0
        /// <summary>
        /// Creates a <see cref="MethodBuilder"/> and implements a default wrapper.
        /// </summary>
        /// <param name="owner">The type that will own this method.</param>
        /// <param name="interfaceType">Type of interface implemented by the <paramref name="owner"/>.</param>
        /// <param name="overrideMethod">Method to override.</param>
        /// <param name="fieldBuilders">Fields specified by the <see paramref="owner"/>.</param>
        /// <returns>MethodBuilder with an already implemented wrapper.</returns>
        public MethodBuilder GenerateInvocation(TypeBuilder owner, Type interfaceType, MethodInfo overrideMethod, IEnumerable <FieldBuilder> fieldBuilders)
        {
            Type[] MakeNullIfEmpty(Type[] input)
            {
                return(input.Length == 0 ? null : input);
            }

            Type[][] MakeNullIfEmptyArray(Type[][] input)
            {
                return(input.All(x => x == null) ? null : input);
            }

            var parameters     = overrideMethod.GetParameters();
            var parameterTypes = parameters.Select(t => t.ParameterType).ToArray();
            var ret            = overrideMethod.ReturnParameter;

            var parameterTypeRequiredCustomModifiers = MakeNullIfEmptyArray(parameters.Select(x => MakeNullIfEmpty(x.GetRequiredCustomModifiers())).ToArray());
            var parameterTypeOptionalCustomModifiers = MakeNullIfEmptyArray(parameters.Select(x => MakeNullIfEmpty(x.GetOptionalCustomModifiers())).ToArray());
            var returnTypeRequiredCustomModifiers    = MakeNullIfEmpty(ret.GetRequiredCustomModifiers());
            var returnTypeOptionalCustomModifiers    = MakeNullIfEmpty(ret.GetOptionalCustomModifiers());

            var result = owner.DefineMethod
                         (
                name: overrideMethod.Name,
                attributes: MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.Final |
                MethodAttributes.HideBySig | MethodAttributes.NewSlot,
                callingConvention: overrideMethod.CallingConvention,
                returnType: overrideMethod.ReturnType,
                returnTypeRequiredCustomModifiers: returnTypeRequiredCustomModifiers,
                returnTypeOptionalCustomModifiers: returnTypeOptionalCustomModifiers,
                parameterTypes: parameterTypes,
                parameterTypeRequiredCustomModifiers: parameterTypeRequiredCustomModifiers,
                parameterTypeOptionalCustomModifiers: parameterTypeOptionalCustomModifiers
                         );

#if !NET35
            result.SetImplementationFlags(MethodImplAttributes.AggressiveInlining);
#endif

            var generator = result.GetILGenerator();
            var fieldName = LibraryInterfaceMapper.GetFieldNameForMethodInfo(overrideMethod);
            var field     = fieldBuilders.First(f => f.Name == fieldName);

            OnInvokeBegin(owner, interfaceType, generator, overrideMethod);
            generator.Emit(OpCodes.Ldarg_0);      //  this
            generator.Emit(OpCodes.Ldfld, field); // MethodNameProc _glMethodName. Initialized by constructor.
            foreach (var item in parameters.Where(p => !p.IsRetval))
            {
                generator.Emit(OpCodes.Ldarg, item.Position + 1); // 0 is `this` so we skip it
            }

            generator.EmitCall(OpCodes.Callvirt, field.FieldType.GetMethod("Invoke"), null);

            OnInvokeEnd(owner, interfaceType, generator, overrideMethod);

            generator.Emit(OpCodes.Ret);

            owner.DefineMethodOverride(result, overrideMethod);

            return(result);
        }