Represents a class that automatically injects a proxy instance instead of an actual service instance.
Inheritance: IPostProcessor
        /// <summary>
        /// Loads an <see cref="IInterceptor"/> derived class into a particular <see cref="IServiceContainer"/> instance
        /// so that the current interceptor type can intercept calls made to services created from the given
        /// target container.
        /// </summary>
        /// <param name="input">The interceptor type.</param>
        /// <returns>By default, this will always return an empty set of container actions. The actual interceptor itself will be injected at the end of the postprocessor chain.</returns>
        public IEnumerable <Action <IServiceContainer> > Load(Type input)
        {
            var typeInstance = Activator.CreateInstance(input);
            var interceptor  = typeInstance as IInterceptor;

            Func <IServiceRequestResult, IInterceptor> getInterceptor = null;

            // Return the interceptor by default
            if (interceptor != null)
            {
                getInterceptor = result =>
                {
                    var target       = result.ActualResult;
                    var container    = result.Container;
                    var methodInvoke = container.GetService <IMethodInvoke <MethodInfo> >();
                    var factory      = container.GetService <IProxyFactory>();

                    // Manually initialize the interceptor
                    var initialize = interceptor as IInitialize;
                    if (initialize != null)
                    {
                        initialize.Initialize(container);
                    }

                    return(new Redirector(() => target, interceptor, factory, methodInvoke));
                };
            }

            if (typeInstance != null && typeInstance is IAroundInvoke)
            {
                // Convert the IAroundInvoke instance into
                // a running interceptor
                var aroundInvoke = typeInstance as IAroundInvoke;
                getInterceptor = result =>
                {
                    var container    = result.Container;
                    var methodInvoke = container.GetService <IMethodInvoke <MethodInfo> >();
                    var factory      = container.GetService <IProxyFactory>();

                    // Manually initialize the interceptor
                    var initialize = aroundInvoke as IInitialize;
                    if (initialize != null)
                    {
                        initialize.Initialize(container);
                    }

                    // HACK: The adapter can't be created until runtime since
                    // the aroundInvoke instance needs an actual target
                    var target  = result.ActualResult;
                    var adapter = new AroundInvokeAdapter(() => target,
                                                          methodInvoke, aroundInvoke);

                    var redirector = new Redirector(() => target, adapter, factory, methodInvoke);

                    return(redirector);
                };
            }

            // The type must implement either the IInterceptor interface
            // or the IAroundInvoke interface
            if (getInterceptor == null)
            {
                return(new Action <IServiceContainer> [0]);
            }

            // Determine which service types should be intercepted
            var attributes =
                from attribute in input.GetCustomAttributes(typeof(InterceptsAttribute), false)
                let currentAttribute = attribute as InterceptsAttribute
                                       where currentAttribute != null
                                       select currentAttribute;

            var interceptedTypes = new Dictionary <Type, HashSet <string> >();

            foreach (var attribute in attributes)
            {
                var serviceName = attribute.ServiceName;
                var serviceType = attribute.TargetType;

                // Keep track of the service name and service type
                // and mark the current type for interception
                // using the current interceptor
                if (!interceptedTypes.ContainsKey(serviceType))
                {
                    interceptedTypes[serviceType] = new HashSet <string>();
                }

                if (!interceptedTypes[serviceType].Contains(serviceName))
                {
                    interceptedTypes[serviceType].Add(serviceName);
                }
            }

            // There must be at least one InterceptsAttribute defined on
            // the input type
            if (interceptedTypes.Count == 0)
            {
                return(new Action <IServiceContainer> [0]);
            }

            // Match the service type with the current type
            Func <IServiceRequestResult, bool> filter = request =>
            {
                var container = request.Container;

                // There must be a valid proxy factory
                if (container == null ||
                    !container.Contains(typeof(IProxyFactory)))
                {
                    return(false);
                }

                var serviceType = request.ServiceType;
                // Ignore requests to intercept IMethodInvoke<MethodInfo>
                if (serviceType == typeof(IMethodInvoke <MethodInfo>))
                {
                    return(false);
                }

                // Sealed types cannot be proxied by default
                if (serviceType.IsSealed)
                {
                    return(false);
                }

                // Match any service name if the service name is blank
                if (request.ServiceName == null &&
                    interceptedTypes.ContainsKey(serviceType))
                {
                    return(true);
                }

                // Match the service name and type
                if (interceptedTypes.ContainsKey(serviceType) &&
                    interceptedTypes[serviceType].Contains(
                        request.ServiceName))
                {
                    return(true);
                }

                if (!serviceType.IsGenericType)
                {
                    return(false);
                }

                // Determine if an interceptor can intercept the
                // entire family of generic types
                var baseDefinition =
                    serviceType.GetGenericTypeDefinition();

                // The list of intercepted types should contain
                // the generic type definition and its matching
                // service name
                var serviceName = request.ServiceName;

                return(interceptedTypes.ContainsKey(baseDefinition) &&
                       interceptedTypes[baseDefinition].Contains(
                           serviceName));
            };

            // Create the proxy using the service request
            Func <IServiceRequestResult, object> createProxy = request => CreateProxyFrom(request, getInterceptor);

            // Place the interceptor at the end of the
            // postprocessor chain
            var injector = new ProxyInjector(filter, createProxy);

            _loaderHost.Plugins.Add(new ProxyContainerPlugin(injector));

            return(new Action <IServiceContainer> [0]);
        }
        /// <summary>
        /// Loads an <see cref="IInterceptor"/> derived class into a particular <see cref="IServiceContainer"/> instance
        /// so that the current interceptor type can intercept calls made to services created from the given
        /// target container.
        /// </summary>
        /// <param name="input">The interceptor type.</param>
        /// <returns>By default, this will always return an empty set of container actions. The actual interceptor itself will be injected at the end of the postprocessor chain.</returns>
        public IEnumerable<Action<IServiceContainer>> Load(Type input)
        {
            object typeInstance = Activator.CreateInstance(input);
            var interceptor = typeInstance as IInterceptor;

            Func<IServiceRequestResult, IInterceptor> getInterceptor = null;

            // Return the interceptor by default
            if (interceptor != null)
            {
                getInterceptor = result =>
                                     {
                                         var target = result.ActualResult;
                                         var container = result.Container;
                                         var methodInvoke = container.GetService<IMethodInvoke<MethodInfo>>();
                                         var factory = container.GetService<IProxyFactory>();

                                         // Manually initialize the interceptor
                                         var initialize = interceptor as IInitialize;
                                         if (initialize != null)
                                             initialize.Initialize(container);

                                         return new Redirector(() => target, interceptor, factory, methodInvoke);
                                     };
            }

            if (typeInstance != null && typeInstance is IAroundInvoke)
            {
                // Convert the IAroundInvoke instance into
                // a running interceptor
                var aroundInvoke = typeInstance as IAroundInvoke;
                getInterceptor = result =>
                                     {
                                         var container = result.Container;
                                         var methodInvoke = container.GetService<IMethodInvoke<MethodInfo>>();
                                         var factory = container.GetService<IProxyFactory>();

                                         // Manually initialize the interceptor
                                         var initialize = aroundInvoke as IInitialize;
                                         if (initialize != null)
                                             initialize.Initialize(container);

                                         // HACK: The adapter can't be created until runtime since
                                         // the aroundInvoke instance needs an actual target
                                         var target = result.ActualResult;
                                         var adapter = new AroundInvokeAdapter(() => target,
                                             methodInvoke, aroundInvoke);

                                         var redirector = new Redirector(() => target, adapter, factory, methodInvoke);

                                         return redirector;
                                     };
            }

            // The type must implement either the IInterceptor interface
            // or the IAroundInvoke interface
            if (getInterceptor == null)
                return new Action<IServiceContainer>[0];

            // Determine which service types should be intercepted
            var attributes = from attribute in input.GetCustomAttributes(typeof(InterceptsAttribute), false)
                             let currentAttribute = attribute as InterceptsAttribute
                             where currentAttribute != null
                             select currentAttribute;

            var interceptedTypes = new Dictionary<Type, HashSet<string>>();
            foreach (var attribute in attributes)
            {

                var serviceName = attribute.ServiceName;
                var serviceType = attribute.TargetType;

                // Keep track of the service name and service type
                // and mark the current type for interception
                // using the current interceptor
                if (!interceptedTypes.ContainsKey(serviceType))
                    interceptedTypes[serviceType] = new HashSet<string>();

                if (!interceptedTypes[serviceType].Contains(serviceName))
                    interceptedTypes[serviceType].Add(serviceName);
            }

            // There must be at least one InterceptsAttribute defined on
            // the input type
            if (interceptedTypes.Count == 0)
                return new Action<IServiceContainer>[0];

            // Match the service type with the current type
            Func<IServiceRequestResult, bool> filter = request =>
                {
                    var container = request.Container;

                    // There must be a valid proxy factory
                    if (container == null || !container.Contains(typeof(IProxyFactory)))
                        return false;

                    var serviceType = request.ServiceType;
                    // Ignore requests to intercept IMethodInvoke<MethodInfo>
                    if (serviceType == typeof(IMethodInvoke<MethodInfo>))
                        return false;

                    // Sealed types cannot be proxied by default
                    if (serviceType.IsSealed)
                        return false;

                    // Match any service name if the service name is blank
                    if (request.ServiceName == null && interceptedTypes.ContainsKey(serviceType))
                        return true;

                    // Match the service name and type
                    if (interceptedTypes.ContainsKey(serviceType) &&
                        interceptedTypes[serviceType].Contains(request.ServiceName))
                        return true;

                    if (!serviceType.IsGenericType)
                        return false;

                    // Determine if an interceptor can intercept the
                    // entire family of generic types
                    var baseDefinition = serviceType.GetGenericTypeDefinition();

                    // The list of intercepted types should contain
                    // the generic type definition and its matching
                    // service name
                    var serviceName = request.ServiceName;

                    return interceptedTypes.ContainsKey(baseDefinition) && interceptedTypes[baseDefinition].Contains(serviceName);
                };

            // Create the proxy using the service request
            Func<IServiceRequestResult, object> createProxy = request => CreateProxyFrom(request, getInterceptor);

            // Place the interceptor at the end of the
            // postprocessor chain
            var injector = new ProxyInjector(filter, createProxy);
            _loaderHost.Plugins.Add(new ProxyContainerPlugin(injector));

            return new Action<IServiceContainer>[0];
        }
 /// <summary>
 /// Initializes the class with the given <see cref="ProxyInjector"/> instance.
 /// </summary>
 /// <param name="injector">The postprocessor that will inject proxies in place of actual service requests.</param>
 internal ProxyContainerPlugin(ProxyInjector injector)
 {
     _injector = injector;
 }
Example #4
0
 /// <summary>
 /// Initializes the class with the given <see cref="ProxyInjector"/> instance.
 /// </summary>
 /// <param name="injector">The postprocessor that will inject proxies in place of actual service requests.</param>
 internal ProxyContainerPlugin(ProxyInjector injector)
 {
     _injector = injector;
 }