public Type CreateInterfaceProxy(Type @interface)
        {
            if ([email protected])
            {
                throw new ArgumentException($"InterfaceType_Must_Be_Interface, {@interface.FullName}", "T");
            }
            var          attributes   = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.Final;
            TypeBuilder  builder      = this._moduleBuilder.DefineType($"{@interface.Name}_Proxy", TypeAttributes.Public, typeof(object), new Type[] { @interface });
            ProxyBuilder proxyBuilder = new ProxyBuilder(builder, @interface);

            proxyBuilder.DefineClassConstructor();
            foreach (var method in @interface.GetMethods().Where(method => !method.IsSpecialName))
            {
                proxyBuilder.DefineInterceptorMethod(method, attributes);
            }
            foreach (var property in @interface.GetProperties())
            {
                var parameterTypes  = property.GetIndexParameters().Select(it => it.ParameterType).ToArray();
                var propertyBuilder = builder.DefineProperty(property.Name, property.Attributes, property.PropertyType, parameterTypes);
                var getMethod       = property.GetMethod;
                if (null != getMethod)
                {
                    propertyBuilder.SetGetMethod(proxyBuilder.DefineInterceptorMethod(getMethod, attributes));
                }
                var setMethod = property.SetMethod;
                if (null != setMethod)
                {
                    propertyBuilder.SetSetMethod(proxyBuilder.DefineInterceptorMethod(setMethod, attributes));
                }
            }
            return(builder.CreateTypeInfo());
        }
        public Type CreateClassProxy(Type @class)
        {
            if (@class.IsSealed)
            {
                throw new ArgumentException($"BaseType_Cannot_Be_Sealed, {@class.FullName}", "TProxy");
            }
            var          builder      = _moduleBuilder.DefineType($"{@class.Name}_Proxy", TypeAttributes.Public | TypeAttributes.Sealed, @class, new Type[] { typeof(IProxy) });
            ProxyBuilder proxyBuilder = new ProxyBuilder(builder, @class);

            proxyBuilder.DefineSubClassConstructor();

            proxyBuilder.DefineProxyMethod();

            foreach (var methodInfo in @class.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).Where(method => method.DeclaringType != typeof(object)))
            {
                if (!methodInfo.IsSpecialName && !methodInfo.IsFinal && methodInfo.IsVirtual)
                {
                    proxyBuilder.DefineInterceptorMethod(methodInfo);
                }
            }

            foreach (var property in @class.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.SetProperty | BindingFlags.GetProperty))
            {
                proxyBuilder.DefineProperty(property);
            }

            return(builder.CreateTypeInfo());
        }
        public Type CreateInterfaceProxy(Type @interface)
        {
            if ([email protected])
            {
                throw new ArgumentException($"InterfaceType_Must_Be_Interface, {@interface.FullName}", "T");
            }
            TypeBuilder  builder      = this._moduleBuilder.DefineType($"{@interface.Name}_Proxy", TypeAttributes.Public, typeof(object), new Type[] { @interface, typeof(IProxy) });
            ProxyBuilder proxyBuilder = new ProxyBuilder(builder, @interface);

            proxyBuilder.DefineClassConstructor();

            proxyBuilder.DefineProxyMethod();

            foreach (var method in @interface.GetMethods().Where(method => !method.IsSpecialName))
            {
                proxyBuilder.DefineInterceptorMethod(method);
            }

            foreach (var property in @interface.GetProperties())
            {
                proxyBuilder.DefineProperty(property);
            }

            return(builder.CreateTypeInfo());
        }
        public Type CreateClassProxy(Type @class)
        {
            if (@class.IsSealed)
            {
                throw new ArgumentException($"BaseType_Cannot_Be_Sealed, {@class.FullName}", "TProxy");
            }
            var          builder      = _moduleBuilder.DefineType($"{@class.Name}_Proxy", TypeAttributes.Public | TypeAttributes.Sealed, @class);
            ProxyBuilder proxyBuilder = new ProxyBuilder(builder, @class);

            proxyBuilder.DefineSubClassConstructor();
            foreach (var methodInfo in @class.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).Where(method => method.DeclaringType != typeof(object)))
            {
                if (!methodInfo.IsSpecialName && !methodInfo.IsFinal)
                {
                    var attributes = GetMethodAttributes(methodInfo);
                    if (null != attributes)
                    {
                        proxyBuilder.DefineInterceptorMethod(methodInfo, attributes.Value);
                    }
                }
            }

            foreach (var property in @class.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.SetProperty | BindingFlags.GetProperty))
            {
                var             parameterTypes  = property.GetIndexParameters().Select(it => it.ParameterType).ToArray();
                PropertyBuilder propertyBuilder = builder.DefineProperty(property.Name, property.Attributes, property.PropertyType, parameterTypes);
                var             getMethod       = property.GetMethod;
                if (getMethod != null && !getMethod.IsFinal)
                {
                    var attributes = GetMethodAttributes(getMethod);
                    if (null != attributes)
                    {
                        propertyBuilder.SetGetMethod(proxyBuilder.DefineInterceptorMethod(getMethod, attributes.Value));
                    }
                }
                var setMethod = property.SetMethod;
                if (setMethod != null && !setMethod.IsFinal)
                {
                    var attributes = GetMethodAttributes(setMethod);
                    if (null != attributes)
                    {
                        propertyBuilder.SetSetMethod(proxyBuilder.DefineInterceptorMethod(setMethod, attributes.Value));
                    }
                }
            }
            return(builder.CreateTypeInfo());
        }