/// <summary>
        /// Create a proxy object that provides interception for <paramref name="target"/>.
        /// </summary>
        /// <param name="t">Type to generate the proxy of.</param>
        /// <param name="target">Object to create the proxy for.</param>
        /// <param name="additionalInterfaces">Additional interfaces the proxy must implement.</param>
        /// <returns>The proxy object.</returns>
        public IInterceptingProxy CreateProxy(Type t, object target, params Type[] additionalInterfaces)
        {
            Guard.ArgumentNotNull(t, "t");
            Guard.ArgumentNotNull(additionalInterfaces, "additionalInterfaces");

            Type interceptorType;
            Type typeToProxy = t;
            bool genericType = false;

            if (t.IsGenericType)
            {
                typeToProxy = t.GetGenericTypeDefinition();
                genericType = true;
            }

            GeneratedTypeKey key = new GeneratedTypeKey(typeToProxy, additionalInterfaces);

            lock (InterceptorClasses)
            {
                if (!InterceptorClasses.TryGetValue(key, out interceptorType))
                {
                    InterfaceInterceptorClassGenerator generator =
                        new InterfaceInterceptorClassGenerator(typeToProxy, additionalInterfaces);
                    interceptorType         = generator.CreateProxyType();
                    InterceptorClasses[key] = interceptorType;
                }
            }

            if (genericType)
            {
                interceptorType = interceptorType.MakeGenericType(t.GetGenericArguments());
            }
            return((IInterceptingProxy)interceptorType.GetConstructors()[0].Invoke(new object[] { target, t }));
        }
        /// <summary>
        /// Create a type to proxy for the given type <paramref name="t"/>.
        /// </summary>
        /// <param name="t">Type to proxy.</param>
        /// <param name="additionalInterfaces">Additional interfaces the proxy must implement.</param>
        /// <returns>New type that can be instantiated instead of the
        /// original type t, and supports interception.</returns>
        public Type CreateProxyType(Type t, params Type[] additionalInterfaces)
        {
            Guard.ArgumentNotNull(t, "t");
            Guard.ArgumentNotNull(additionalInterfaces, "additionalInterfaces");

            if (!CanIntercept(t))
            {
                throw new InvalidOperationException(
                          string.Format(CultureInfo.CurrentCulture, Resources.InterceptionNotSupported, t.Name));
            }

            Type interceptorType;
            Type typeToDerive = t;
            bool genericType  = false;

            if (t.IsGenericType)
            {
                typeToDerive = t.GetGenericTypeDefinition();
                genericType  = true;
            }

            GeneratedTypeKey key = new GeneratedTypeKey(typeToDerive, additionalInterfaces);

            lock (DerivedClasses)
            {
                if (!DerivedClasses.TryGetValue(key, out interceptorType))
                {
                    InterceptingClassGenerator generator =
                        new InterceptingClassGenerator(typeToDerive, additionalInterfaces);
                    interceptorType     = generator.GenerateType();
                    DerivedClasses[key] = interceptorType;
                }
            }

            if (genericType)
            {
                interceptorType = interceptorType.MakeGenericType(t.GetGenericArguments());
            }

            return(interceptorType);
        }