/// <summary>
        /// Create a proxy wrapping specified target instance and interceptors.
        /// </summary>
        /// <param name="typeToProxy">The declaration type of proxy to create.</param>
        /// <param name="target">The target instance wrapped by the created proxy.</param>
        /// <param name="initerceptors">The interceptors specific to each methods.</param>
        /// <returns>The proxy wrapping the specified target instance.</returns>
        /// <exception cref="ArgumentNullException">The argument <paramref name="typeToProxy"/> is null.</exception>
        /// <exception cref="ArgumentNullException">The argument <paramref name="target"/> is null.</exception>
        /// <exception cref="ArgumentNullException">The argument <paramref name="initerceptors"/> is null.</exception>
        protected override object CreateProxyCore(Type typeToProxy, object target, IDictionary <MethodInfo, InterceptorDelegate> initerceptors)
        {
            Guard.ArgumentNotNull(typeToProxy, nameof(typeToProxy));
            Guard.ArgumentNotNull(target, nameof(target));
            Guard.ArgumentNotNull(initerceptors, nameof(initerceptors));

            if (!initerceptors.Any())
            {
                return(target);
            }
            IDictionary <MethodInfo, IInterceptor> dic = initerceptors.ToDictionary(it => it.Key, it => (IInterceptor) new DynamicProxyInterceptor(it.Value));
            var selector = new DynamicProxyInterceptorSelector(dic);
            var options  = new ProxyGenerationOptions {
                Selector = selector
            };

            if (typeToProxy.GetTypeInfo().IsInterface)
            {
                return(_proxyGenerator.CreateInterfaceProxyWithTarget(typeToProxy, target, options, dic.Values.ToArray()));
            }
            else
            {
                return(_proxyGenerator.CreateClassProxyWithTarget(typeToProxy, target, options, dic.Values.ToArray()));
            }
        }
        /// <summary>
        /// Create a proxy wrapping specified target instance.
        /// </summary>
        /// <param name="typeToIntercept">The type to intercept.</param>
        /// <param name="target">The target.</param>
        /// <param name="interceptors">The interceptors.</param>
        /// <returns></returns>
        protected override object Wrap(Type typeToIntercept, object target, InterceptorDecoration interceptors)
        {
            var dictionary = interceptors.Interceptors
                             .ToDictionary(it => it.Key, it => new DynamicProxyInterceptor(it.Value).ToInterceptor());
            var selector = new DynamicProxyInterceptorSelector(dictionary.ToDictionary(it => it.Key, it => it.Value));
            var options  = new ProxyGenerationOptions {
                Selector = selector
            };

            return(_proxyGenerator.CreateInterfaceProxyWithTarget(typeToIntercept, target, dictionary.Values.ToArray()));
        }
        /// <summary>
        /// Create an interceptable proxy instance.
        /// </summary>
        /// <param name="typeToIntercept">The type to intercept.</param>
        /// <param name="serviceProvider">The <see cref="T:System.IServiceProvider" /> used to provide dependent service instances.</param>
        /// <param name="interceptors">The <see cref="T:Dora.DynamicProxy.InterceptorDecoration" /> representing which interceptors are applied to which members of a type to intercept.</param>
        /// <returns>
        /// The interceptable proxy instance.
        /// </returns>
        protected override object Create(Type typeToIntercept, IServiceProvider serviceProvider, InterceptorDecoration interceptors)
        {
            var dictionary = interceptors.Interceptors
                             .ToDictionary(it => it.Key, it => new DynamicProxyInterceptor(it.Value).ToInterceptor());
            var selector = new DynamicProxyInterceptorSelector(dictionary.ToDictionary(it => it.Key, it => it.Value));
            var options  = new ProxyGenerationOptions {
                Selector = selector
            };

            return(_proxyGenerator.CreateClassProxy(typeToIntercept, options, dictionary.Values.ToArray()));
        }
        /// <summary>
        /// Create a proxy wrapping specified target instance.
        /// </summary>
        /// <param name="typeToIntercept">The declaration type of proxy to create.</param>
        /// <param name="target">The target instance wrapped by the created proxy.</param>
        /// <returns>
        /// The proxy wrapping the specified target instance.
        /// </returns>
        public object Wrap(Type typeToIntercept, object target)
        {
            Guard.ArgumentNotNull(typeToIntercept, nameof(typeToIntercept));
            Guard.ArgumentNotNull(target, nameof(target));
            var interceptorDecoration = _interceptorCollector.GetInterceptors(typeToIntercept, target.GetType());
            var interceptors          = interceptorDecoration.Interceptors
                                        .ToDictionary(it => it.Key, it => new DynamicProxyInterceptor(it.Value).ToInterceptor());
            var selector = new DynamicProxyInterceptorSelector(interceptors.ToDictionary(it => it.Key, it => it.Value));
            var options  = new ProxyGenerationOptions {
                Selector = selector
            };

            return(_proxyGenerator.CreateInterfaceProxyWithTarget(typeToIntercept, target, interceptors.Values.ToArray()));
        }
        /// <summary>
        /// Creates the specified type to intercept.
        /// </summary>
        /// <param name="typeToIntercept">The type to intercept.</param>
        /// <param name="serviceProvider">The service provider.</param>
        /// <param name="targetAccessor">The target accessor.</param>
        /// <returns>The proxy wrapping the specified target instance.</returns>
        public object Create(Type typeToIntercept, IServiceProvider serviceProvider, Func <object> targetAccessor = null)
        {
            var interceptorDecoration = _interceptorCollector.GetInterceptors(typeToIntercept);

            if (interceptorDecoration.IsEmpty)
            {
                return(targetAccessor == null
                    ? serviceProvider.GetService(typeToIntercept)
                    : targetAccessor());
            }

            var interceptors = interceptorDecoration.Interceptors
                               .ToDictionary(it => it.Key, it => new DynamicProxyInterceptor(it.Value).ToInterceptor());
            var selector = new DynamicProxyInterceptorSelector(interceptors.ToDictionary(it => it.Key, it => it.Value));
            var options  = new ProxyGenerationOptions {
                Selector = selector
            };

            return(_proxyGenerator.CreateClassProxy(typeToIntercept, options, interceptors.Values.ToArray()));
        }