コード例 #1
0
ファイル: InstanceDecorator.cs プロジェクト: weelink/Autofac
        internal static object TryDecorateRegistration(
            Service service,
            IComponentRegistration registration,
            object instance,
            IComponentContext context,
            IEnumerable <Parameter> parameters)
        {
            if (service is DecoratorService ||
                !(service is IServiceWithType serviceWithType) ||
                registration is ExternalComponentRegistration)
            {
                return(instance);
            }

            var decoratorRegistrations = context.ComponentRegistry.DecoratorsFor(serviceWithType);

            if (decoratorRegistrations.Count == 0)
            {
                return(instance);
            }

            var serviceType       = serviceWithType.ServiceType;
            var resolveParameters = parameters as Parameter[] ?? parameters.ToArray();

            var instanceType     = instance.GetType();
            var decoratorContext = DecoratorContext.Create(instanceType, serviceType, instance);
            var decoratorCount   = decoratorRegistrations.Count;

            for (var index = 0; index < decoratorCount; index++)
            {
                var decoratorRegistration = decoratorRegistrations[index];
                var decoratorService      = decoratorRegistration.Services.OfType <DecoratorService>().First();
                if (!decoratorService.Condition(decoratorContext))
                {
                    continue;
                }

                var serviceParameter = new TypedParameter(serviceType, instance);
                var contextParameter = new TypedParameter(typeof(IDecoratorContext), decoratorContext);

                var invokeParameters = new Parameter[resolveParameters.Length + 2];
                for (var i = 0; i < resolveParameters.Length; i++)
                {
                    invokeParameters[i] = resolveParameters[i];
                }

                invokeParameters[invokeParameters.Length - 2] = serviceParameter;
                invokeParameters[invokeParameters.Length - 1] = contextParameter;

                var resolveRequest = new ResolveRequest(decoratorService, decoratorRegistration, invokeParameters);
                instance = context.ResolveComponent(resolveRequest);

                if (index < decoratorCount - 1)
                {
                    decoratorContext = decoratorContext.UpdateContext(instance);
                }
            }

            return(instance);
        }
コード例 #2
0
        internal static object TryDecorateRegistration(
            IComponentRegistration registration,
            object instance,
            IComponentContext context,
            IEnumerable <Parameter> parameters)
        {
            var instanceType = instance.GetType();

            // Issue #965: Do not apply the decorator if the registration is for an adapter.
            if (registration.IsAdapting())
            {
                return(instance);
            }

            var decoratorRegistrations = context.ComponentRegistry.DecoratorsFor(registration);

            // ReSharper disable once PossibleMultipleEnumeration
            if (!decoratorRegistrations.Any())
            {
                return(instance);
            }

            // ReSharper disable once PossibleMultipleEnumeration
            var decorators = decoratorRegistrations
                             .Select(r => new
            {
                Registration = r,
                Service      = r.Services.OfType <DecoratorService>().First()
            })
                             .ToArray();

            if (decorators.Length == 0)
            {
                return(instance);
            }

            var serviceType       = decorators[0].Service.ServiceType;
            var resolveParameters = parameters as Parameter[] ?? parameters.ToArray();

            var decoratorContext = DecoratorContext.Create(instanceType, serviceType, instance);

            foreach (var decorator in decorators)
            {
                if (!decorator.Service.Condition(decoratorContext))
                {
                    continue;
                }

                var serviceParameter = new TypedParameter(serviceType, instance);
                var contextParameter = new TypedParameter(typeof(IDecoratorContext), decoratorContext);
                var invokeParameters = resolveParameters.Concat(new Parameter[] { serviceParameter, contextParameter });
                instance = context.ResolveComponent(decorator.Registration, invokeParameters);

                decoratorContext = decoratorContext.UpdateContext(instance);
            }

            return(instance);
        }
コード例 #3
0
        /// <inheritdoc/>
        public void Execute(ResolveRequestContext context, Action <ResolveRequestContext> next)
        {
            // Go down the pipeline first, need that instance.
            next(context);

            // Don't do this if we didn't activate an instance (for example because of decorator instance sharing).
            if (context.Instance is null)
            {
                return;
            }

            // Check if decoration is disabled.
            if (context.Registration.Options.HasOption(RegistrationOptions.DisableDecoration))
            {
                return;
            }

            if (!(context.Operation is IDependencyTrackingResolveOperation dependencyTrackingResolveOperation))
            {
                // Skipping decorator middleware, since IResolveOperation is not IDependencyTrackingResolveOperation
                // Which contains required functionality EnterNewDependencyDetectionBlock
                return;
            }

            // This middleware is only ever added to IServiceWithType pipelines, so this cast will always succeed.
            var swt = (IServiceWithType)context.Service;

            var serviceType = swt.ServiceType;

            if (context.DecoratorContext is null)
            {
                context.DecoratorContext = DecoratorContext.Create(context.Instance.GetType(), serviceType, context.Instance);
            }
            else
            {
                // Update the context with the previous decorator's output.
                // Doing this here, rather than in the decorator middleware that resulted in the instance
                // means we do not need to needlessly update the decorator context on the final decorator.
                context.DecoratorContext = context.DecoratorContext.UpdateContext(context.Instance);
            }

            if (!_decoratorService.Condition(context.DecoratorContext))
            {
                return;
            }

            var serviceParameter = new TypedParameter(serviceType, context.DecoratorContext.CurrentInstance);
            var contextParameter = new TypedParameter(typeof(IDecoratorContext), context.DecoratorContext);

            Parameter[] resolveParameters;

            var parameterCount = context.Parameters.Count();

            if (parameterCount == 0)
            {
                resolveParameters = new Parameter[] { serviceParameter, contextParameter };
            }
            else
            {
                resolveParameters = new Parameter[parameterCount + 2];
                var idx = 0;

                foreach (var existing in context.Parameters)
                {
                    resolveParameters[idx] = existing;
                    idx++;
                }

                resolveParameters[idx++] = serviceParameter;
                resolveParameters[idx++] = contextParameter;
            }

            // We're going to define a service registration that does not contain any service
            // pipeline additions.
            // Adding a service pipeline middleware to a decorator service is not valid anyway.
            var resolveRequest = new ResolveRequest(
                _decoratorService,
                new ServiceRegistration(ServicePipelines.DefaultServicePipeline, _decoratorRegistration),
                resolveParameters,
                context.Registration);

            using (dependencyTrackingResolveOperation.EnterNewDependencyDetectionBlock())
            {
                var decoratedInstance = context.ResolveComponent(resolveRequest);

                context.Instance = decoratedInstance;
            }
        }