Exemple #1
0
        /// <summary>
        /// Create proxy type of specified type.
        /// </summary>
        /// <param name="moduleBuilder">Instance of <see cref="System.Reflection.Emit.ModuleBuilder"/>.</param>
        /// <param name="type">Type of interface to be implemented by the proxy type.</param>
        /// <returns>Generated proxy type that implements the specified interface.</returns>
        public static Type CreateProxyTypeOf(this ModuleBuilder moduleBuilder, Type type)
        {
            if (moduleBuilder is null)
            {
                throw new ArgumentNullException(nameof(moduleBuilder));
            }

            if (type is null)
            {
                throw new ArgumentNullException(nameof(type));
            }

            if (!type.IsInterface)
            {
                throw new InvalidOperationException();
            }

            TypeBuilder typeBuilder = moduleBuilder.GetProxyTypeBuilder(type);

            typeBuilder.AddDefaultConstructor();

            var interfaces = type.GetInterfaces();

            // Properties are added as real getters and setters,
            // methods are added as dummy methods.
            var propertyInfos = type.GetProperties().Union(interfaces.SelectMany(i => i.GetProperties())).ToArray();

            var properties = propertyInfos.ToDictionary(p => p.Name, p => p.PropertyType);

            // Filter methods which names starts with get_ or set_ to not add as methods because they are added as properties.
            MethodInfo[] methods     = type.GetMethods().Union(interfaces.SelectMany(i => i.GetMethods())).ToArray();
            var          methodInfos = new List <MethodInfo>(methods.Length);

            foreach (var methodInfo in methods)
            {
                if (methodInfo.Name.StartsWith("get_", StringComparison.InvariantCulture) && methodInfo.GetParameters().Length == 0)
                {
                    // This method is property getter.
                    properties.TryAdd(methodInfo.Name.Substring("get_".Length), methodInfo.ReturnType);
                }
                else if (methodInfo.Name.StartsWith("set_", StringComparison.InvariantCulture) && methodInfo.GetParameters().Length == 1)
                {
                    // This method is property setter.
                    properties.TryAdd(methodInfo.Name.Substring("set_".Length), methodInfo.ReturnType);
                }
                else
                {
                    // This does not look like property.
                    methodInfos.Add(methodInfo);
                }
            }

            methodInfos.TrimExcess();

            // Add properties.
            foreach (var property in properties)
            {
                typeBuilder.AddProperty(property.Key, property.Value, methods);
            }

            // Add methods.
            foreach (var methodInfo in methodInfos)
            {
                typeBuilder.AddDummyMethod(methodInfo);
            }

            return(typeBuilder.CreateType());
        }