/// <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)); } }
/// <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()); }