Expression IRegistry.GetDecoratorExpressionOrDefault(Request request) { // Decorators for non service types are not supported. if (request.FactoryType != FactoryType.Service) return null; // We are already resolving decorator for the service, so stop now. var parent = request.GetNonWrapperParentOrDefault(); if (parent != null && parent.DecoratedFactoryID == request.FactoryID) return null; var serviceType = request.ServiceType; var decoratorFuncType = typeof(Func<,>).MakeGenericType(serviceType, serviceType); LambdaExpression resultFuncDecorator = null; var funcDecorators = _decorators.GetValueOrDefault(decoratorFuncType); if (funcDecorators != null) { var decoratorRequest = request.MakeDecorated(); for (var i = 0; i < funcDecorators.Length; i++) { var decorator = funcDecorators[i].Factory; if (((DecoratorSetup)decorator.Setup).IsApplicable(request)) { var newDecorator = decorator.GetExpression(decoratorRequest, this); if (resultFuncDecorator == null) { var decorated = Expression.Parameter(serviceType, "decorated"); resultFuncDecorator = Expression.Lambda(Expression.Invoke(newDecorator, decorated), decorated); } else { var decorateDecorator = Expression.Invoke(newDecorator, resultFuncDecorator.Body); resultFuncDecorator = Expression.Lambda(decorateDecorator, resultFuncDecorator.Parameters[0]); } } } } IEnumerable<DecoratorsEntry> decorators = _decorators.GetValueOrDefault(serviceType); var openGenericDecoratorIndex = decorators == null ? 0 : ((DecoratorsEntry[])decorators).Length; if (request.OpenGenericServiceType != null) { var openGenericDecorators = _decorators.GetValueOrDefault(request.OpenGenericServiceType); if (openGenericDecorators != null) decorators = decorators == null ? openGenericDecorators : decorators.Concat(openGenericDecorators); } Expression resultDecorator = resultFuncDecorator; if (decorators != null) { var decoratorRequest = request.MakeDecorated(); var decoratorIndex = 0; var enumerator = decorators.GetEnumerator(); while (enumerator.MoveNext()) { var decorator = enumerator.Current.ThrowIfNull(); var factory = decorator.Factory; if (((DecoratorSetup)factory.Setup).IsApplicable(request)) { // Cache closed generic registration produced by open-generic decorator. if (decoratorIndex++ >= openGenericDecoratorIndex) factory = Register(factory.GetFactoryPerRequestOrDefault(request, this), serviceType, null); if (decorator.CachedExpression == null) { IList<Type> unusedFunArgs; var funcExpr = factory .GetFuncWithArgsOrDefault(decoratorFuncType, decoratorRequest, this, out unusedFunArgs) .ThrowIfNull(Error.DECORATOR_FACTORY_SHOULD_SUPPORT_FUNC_RESOLUTION, decoratorFuncType); decorator.CachedExpression = unusedFunArgs != null ? funcExpr.Body : funcExpr; } if (resultDecorator == null || !(decorator.CachedExpression is LambdaExpression)) resultDecorator = decorator.CachedExpression; else { if (!(resultDecorator is LambdaExpression)) resultDecorator = Expression.Invoke(decorator.CachedExpression, resultDecorator); else { var prevDecorators = ((LambdaExpression)resultDecorator); var decorateDecorator = Expression.Invoke(decorator.CachedExpression, prevDecorators.Body); resultDecorator = Expression.Lambda(decorateDecorator, prevDecorators.Parameters[0]); } } } } } return resultDecorator; }