Example #1
0
        /// <summary>
        ///     Create the methods add_ remove_ and invoke_ (custom) event-name
        /// </summary>
        /// <param name="typeBuilder">TypeBuilder</param>
        /// <param name="eventInfo">eventInfo</param>
        /// <param name="baseMethods">List of string with the method names of the base class, this is used to decide what can be skipped</param>
        internal static void BuildEvent(TypeBuilder typeBuilder, EventInfo eventInfo, IList <string> baseMethods)
        {
            if (eventInfo == null)
            {
                throw new ArgumentNullException(nameof(eventInfo));
            }

            var parameters     = eventInfo.EventHandlerType.GetMethod("Invoke", AllBindings)?.GetParameters() ?? new ParameterInfo[] {};
            var parameterTypes = (
                from parameterInfo in parameters
                select parameterInfo.ParameterType).ToArray();

            // invoke_ this method is used by the EventObservable of Dapplo.Utils
            var methodName = $"invoke_{eventInfo.Name}";

            if (!baseMethods.Contains(methodName))
            {
                var methodBuilder = typeBuilder.DefineMethod(methodName, DefaultMethodAttributes);
                methodBuilder.SetParameters(parameterTypes);
                methodBuilder.SetReturnType(typeof(void));
                IlMethodBuilder.GenerateForwardingIlMethod(methodBuilder, methodName, parameters.Length, typeof(void));
            }

            // add_
            methodName = $"add_{eventInfo.Name}";
            if (!baseMethods.Contains(methodName))
            {
                var methodBuilder = typeBuilder.DefineMethod(methodName, DefaultMethodAttributes);
                methodBuilder.SetParameters(eventInfo.EventHandlerType);
                methodBuilder.SetReturnType(typeof(void));

                IlMethodBuilder.GenerateForwardingIlMethod(methodBuilder, methodName, 1, typeof(void));
            }

            // remove_
            methodName = $"remove_{eventInfo.Name}";
            if (!baseMethods.Contains(methodName))
            {
                var methodBuilder = typeBuilder.DefineMethod(methodName, DefaultMethodAttributes);
                methodBuilder.SetParameters(eventInfo.EventHandlerType);
                methodBuilder.SetReturnType(typeof(void));

                IlMethodBuilder.GenerateForwardingIlMethod(methodBuilder, methodName, 1, typeof(void));
            }
        }
Example #2
0
        /// <summary>
        ///     Creates an implementation as Type for a given interface, which can be intercepted
        /// </summary>
        /// <param name="typeName">Name of the type to generate</param>
        /// <param name="implementingInterfaces">Interfaces to implement</param>
        /// <param name="baseType">Type as base</param>
        /// <returns>Type</returns>
        public Type CreateType(string typeName, Type[] implementingInterfaces, Type baseType = null)
        {
            Log.Verbose().WriteLine("Creating type {0}", typeName);

            // Make sure to return the type from "cache" if possible
            if (TryGetType(typeName, out var cachedType))
            {
                return(cachedType);
            }

            // The base type always have a value, normally everything extends object
            if (baseType == null)
            {
                baseType = typeof(object);
            }

            // Create the type, and let it implement our interface
            var typeBuilder = _moduleBuilder.DefineType(typeName,
                                                        TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.Sealed,
                                                        baseType, implementingInterfaces);

            // Make a collection of already implemented properties
            var baseProperties = baseType.GetRuntimeProperties().Select(x => x.Name).ToList();

            var propertyInfos =
                from iface in implementingInterfaces
                from propertyInfo in iface.GetProperties()
                select propertyInfo;

            var processedProperties = new Dictionary <string, Type>();

            foreach (var propertyInfo in propertyInfos)
            {
                if (processedProperties.ContainsKey(propertyInfo.Name))
                {
                    continue;
                }
                if (baseProperties.Contains(propertyInfo.Name))
                {
                    continue;
                }
                if (!propertyInfo.CanRead && !propertyInfo.CanWrite)
                {
                    continue;
                }

                // Create get and/or set
                IlGetSetBuilder.BuildGetSet(typeBuilder, propertyInfo);

                processedProperties.Add(propertyInfo.Name, propertyInfo.DeclaringType);
            }

            // Make a collection of already implemented method
            var baseMethods = baseType.GetRuntimeMethods().Select(x => x.Name).ToList();

            var methodInfos =
                from iface in implementingInterfaces
                from methodInfo in iface.GetMethods()
                select methodInfo;

            foreach (var methodInfo in methodInfos)
            {
                if (baseMethods.Contains(methodInfo.Name))
                {
                    continue;
                }
                if (SpecialPrefixes.Any(x => methodInfo.Name.StartsWith(x)))
                {
                    continue;
                }
                IlMethodBuilder.BuildMethod(typeBuilder, methodInfo);
            }

            // Now generate the methods for the event redirections
            var eventInfos =
                from iface in implementingInterfaces
                from eventInfo in iface.GetEvents()
                select eventInfo;

            foreach (var eventInfo in eventInfos)
            {
                IlEventBuilder.BuildEvent(typeBuilder, eventInfo, baseMethods);
            }

            Log.Verbose().WriteLine("Created type {0}", typeName);
            return(typeBuilder.CreateType());
        }