/// <summary> /// Get activation expression for export strategies /// </summary> /// <param name="scope"></param> /// <param name="request"></param> /// <param name="arrayElementType"></param> /// <returns></returns> protected virtual List <IActivationExpressionResult> GetActivationExpressionResultsFromStrategies(IInjectionScope scope, IActivationExpressionRequest request, Type arrayElementType) { var parentStrategy = GetRequestingStrategy(request); List <object> keys = null; var collection = scope.StrategyCollectionContainer.GetActivationStrategyCollection(arrayElementType); var expressions = new List <IActivationExpressionResult>(); if (request.LocateKey != null) { var enumerableKey = request.LocateKey as IEnumerable; if (enumerableKey != null && !(request.LocateKey is string)) { keys = new List <object>(); foreach (var value in enumerableKey) { keys.Add(value); } } else { keys = new List <object> { request.LocateKey }; } } if (collection != null) { if (keys != null) { for (var i = 0; i < keys.Count;) { var strategy = collection.GetKeyedStrategy(keys[i]); if (strategy != null && parentStrategy != strategy) { var newRequest = request.NewRequest(arrayElementType, request.RequestingStrategy, request.RequestingStrategy?.ActivationType, request.RequestType, request.Info, true); var expression = strategy.GetActivationExpression(scope, newRequest); if (expression != null) { expressions.Add(expression); keys.RemoveAt(i); } else { i++; } } else { i++; } } } else { foreach (var strategy in collection.GetStrategies()) { // skip as part of the composite pattern if (strategy == parentStrategy) { continue; } // filter strategies if (request.Filter != null && !request.Filter(strategy)) { continue; } var newRequest = request.NewRequest(arrayElementType, request.RequestingStrategy, request.RequestingStrategy?.ActivationType, request.RequestType, request.Info, true); var expression = strategy.GetActivationExpression(scope, newRequest); if (expression != null) { expressions.Add(expression); } } } } // check for generic if (arrayElementType.IsConstructedGenericType) { var genericType = arrayElementType.GetGenericTypeDefinition(); var strategies = scope.StrategyCollectionContainer.GetActivationStrategyCollection(genericType); if (strategies != null) { if (keys != null) { for (var i = 0; i < keys.Count;) { var strategy = strategies.GetKeyedStrategy(keys[i]); if (strategy != null && strategy != parentStrategy) { var newRequest = request.NewRequest(arrayElementType, request.RequestingStrategy, request.RequestingStrategy?.ActivationType, request.RequestType, request.Info, true); var expression = strategy.GetActivationExpression(scope, newRequest); if (expression != null) { expressions.Add(expression); keys.RemoveAt(i); } else { i++; } } else { i++; } } } else { foreach (var strategy in strategies.GetStrategies()) { // skip as part of the composite pattern if (strategy == parentStrategy) { continue; } // filter strategies if (request.Filter != null && !request.Filter(strategy)) { continue; } var newRequest = request.NewRequest(arrayElementType, request.RequestingStrategy, request.RequestingStrategy?.ActivationType, request.RequestType, request.Info, true); var expression = strategy.GetActivationExpression(scope, newRequest); if (expression != null) { expressions.Add(expression); } } } } } if (expressions.Count == 0) { ProcessWrappers(scope, arrayElementType, request, expressions); } return(expressions); }
/// <summary> /// Sets up wrappers for request /// </summary> /// <param name="scope"></param> /// <param name="request"></param> /// <returns></returns> public bool SetupWrappersForRequest(IInjectionScope scope, IActivationExpressionRequest request) { Type wrappedType; var wrappers = GetWrappers(scope, request.ActivationType, request, out wrappedType); if (wrappers != ImmutableLinkedList <IActivationPathNode> .Empty) { if (request.DecoratorPathNode != null && wrappedType.GetTypeInfo().IsAssignableFrom(request.DecoratorPathNode.Strategy.ActivationType.GetTypeInfo())) { var decorator = request.PopDecoratorPathNode(); wrappers = ImmutableLinkedList <IActivationPathNode> .Empty.Add(decorator).AddRange(wrappers.Reverse()); } else { var collection = GetWrappedTypeFromStrategiesCollection(scope, wrappedType); if (collection == null) { lock (scope.GetLockObject(InjectionScope.ActivationStrategyAddLockName)) { var newRequest = request.NewRequest(wrappedType, request.RequestingStrategy, request.InjectedType, request.RequestType, request.Info, false, true); request.Services.Compiler.ProcessMissingStrategyProviders(scope, newRequest); } collection = GetWrappedTypeFromStrategiesCollection(scope, wrappedType); } if (collection != null) { if (request.LocateKey != null) { var strategy = collection.GetKeyedStrategy(request.LocateKey); if (strategy != null) { wrappers = ImmutableLinkedList <IActivationPathNode> .Empty .Add(new WrapperActivationPathNode(strategy, wrappedType, null)) .AddRange(wrappers.Reverse()); } } else { var primary = request.Filter == null?collection.GetPrimary() : null; if (primary != null && primary != request.RequestingStrategy) { wrappers = ImmutableLinkedList <IActivationPathNode> .Empty .Add(new WrapperActivationPathNode(primary, wrappedType, null)) .AddRange(wrappers.Reverse()); } else { foreach (var strategy in collection.GetStrategies()) { var pass = true; if (strategy.HasConditions) { foreach (var condition in strategy.Conditions) { if (!condition.MeetsCondition(strategy, request.GetStaticInjectionContext())) { pass = false; break; } } } if (pass && request.RequestingStrategy != strategy && (request.Filter == null || request.Filter(strategy))) { wrappers = ImmutableLinkedList <IActivationPathNode> .Empty .Add(new WrapperActivationPathNode(strategy, wrappedType, null)) .AddRange(wrappers.Reverse()); } } } } } else if (!wrappedType.IsArray && (!wrappedType.IsConstructedGenericType || wrappedType.GetGenericTypeDefinition() != typeof(IEnumerable <>))) { return(false); } } request.SetWrapperPath(wrappers); return(true); } return(false); }
/// <summary> /// Get an activation expression for a request /// </summary> /// <param name="scope">scope for request</param> /// <param name="request">request</param> /// <returns></returns> public IActivationExpressionResult GetActivationExpression(IInjectionScope scope, IActivationExpressionRequest request) { Type wrappedType; var wrappers = GetWrappers(scope, request.ActivationType, request, out wrappedType); if (wrappers != ImmutableLinkedList <IActivationPathNode> .Empty) { if (request.DecoratorPathNode != null && wrappedType.GetTypeInfo().IsAssignableFrom(request.DecoratorPathNode.Strategy.ActivationType.GetTypeInfo())) { var decorator = request.PopDecoratorPathNode(); wrappers = ImmutableLinkedList <IActivationPathNode> .Empty.Add(decorator).AddRange(wrappers.Reverse()); } else { var collection = scope.StrategyCollectionContainer.GetActivationStrategyCollection(wrappedType); if (collection == null && wrappedType.IsConstructedGenericType) { var generic = wrappedType.GetGenericTypeDefinition(); collection = scope.StrategyCollectionContainer.GetActivationStrategyCollection(generic); } if (collection != null) { var primary = request.Filter == null?collection.GetPrimary() : null; if (primary != null) { wrappers = ImmutableLinkedList <IActivationPathNode> .Empty.Add(new WrapperActivationPathNode(primary, wrappedType, null)).AddRange(wrappers.Reverse()); } else { foreach (var strategy in collection.GetStrategies()) { var pass = true; if (strategy.HasConditions) { foreach (var condition in strategy.Conditions) { if (!condition.MeetsCondition(strategy, request.GetStaticInjectionContext())) { pass = false; break; } } } if (pass && (request.Filter == null || request.Filter(strategy))) { wrappers = ImmutableLinkedList <IActivationPathNode> .Empty.Add(new WrapperActivationPathNode(strategy, wrappedType, null)).AddRange(wrappers.Reverse()); } } } } else { return(null); } } request.SetWrapperPath(wrappers); var wrapper = request.PopWrapperPathNode(); return(wrapper.GetActivationExpression(scope, request)); } return(null); }