/// <summary> /// Find decorators for a given type /// </summary> /// <param name="scope"></param> /// <param name="request"></param> /// <param name="type"></param> /// <param name="strategy"></param> /// <returns></returns> protected virtual List <ICompiledDecoratorStrategy> FindDecoratorsForType(IInjectionScope scope, IActivationExpressionRequest request, Type type, ICompiledExportStrategy strategy) { List <ICompiledDecoratorStrategy> decorators = new List <ICompiledDecoratorStrategy>(); StaticInjectionContext staticInjectionContext = null; var collection = scope.DecoratorCollectionContainer.GetActivationStrategyCollection(type); if (collection != null) { foreach (var decorator in collection.GetStrategies()) { if (decorator.HasConditions) { if (staticInjectionContext == null) { staticInjectionContext = request.GetStaticInjectionContext(); } if (!decorator.Conditions.All( condition => condition.MeetsCondition(strategy, staticInjectionContext))) { continue; } } decorators.Add(decorator); } } if (type.IsConstructedGenericType) { var generic = type.GetGenericTypeDefinition(); collection = scope.DecoratorCollectionContainer.GetActivationStrategyCollection(generic); if (collection != null) { foreach (var decorator in collection.GetStrategies()) { if (decorator.HasConditions) { if (staticInjectionContext == null) { staticInjectionContext = request.GetStaticInjectionContext(); } if (!decorator.Conditions.All( condition => condition.MeetsCondition(strategy, staticInjectionContext))) { continue; } } decorators.Add(decorator); } } } return(decorators); }
/// <summary> /// Applies null check and disposal scope tracking logic to an expression /// </summary> /// <param name="scope"></param> /// <param name="request"></param> /// <param name="expression"></param> /// <param name="allowDisposableTracking"></param> /// <returns></returns> public static Expression ApplyNullCheckAndAddDisposal(IInjectionScope scope, IActivationExpressionRequest request, Expression expression, bool allowDisposableTracking) { if (expression.Type != request.ActivationType && !ReflectionService.CheckTypeIsBasedOnAnotherType(expression.Type, request.ActivationType)) { expression = Expression.Convert(expression, request.ActivationType); } if (!allowDisposableTracking) { if (request.DefaultValue != null) { var method = typeof(ExpressionUtilities).GetRuntimeMethods() .FirstOrDefault(m => m.Name == "ValueOrDefault"); var closedMethod = method.MakeGenericMethod(request.ActivationType); return(Expression.Call(closedMethod, expression, Expression.Constant(request.DefaultValue.DefaultValue, request.ActivationType))); } if (!scope.ScopeConfiguration.Behaviors.AllowInstanceAndFactoryToReturnNull && request.IsRequired) { var closedMethod = CheckForNullMethodInfo.MakeGenericMethod(request.ActivationType); return(Expression.Call(closedMethod, Expression.Constant(request.GetStaticInjectionContext()), expression)); } return(expression); } if (request.DefaultValue != null) { var method = typeof(ExpressionUtilities).GetRuntimeMethods() .FirstOrDefault(m => m.Name == "AddToDisposableScopeOrDefault"); var closedMethod = method.MakeGenericMethod(request.ActivationType); return(Expression.Call(closedMethod, request.DisposalScopeExpression, expression, Expression.Constant(request.DefaultValue.DefaultValue, request.ActivationType))); } if (scope.ScopeConfiguration.Behaviors.AllowInstanceAndFactoryToReturnNull || !request.IsRequired) { var closedMethod = AddToDisposalScopeMethodInfo.MakeGenericMethod(request.ActivationType); return(Expression.Call(closedMethod, request.DisposalScopeExpression, expression)); } else { var closedMethod = CheckForNullAndAddToDisposalScopeMethodInfo.MakeGenericMethod(request.ActivationType); return(Expression.Call(closedMethod, request.DisposalScopeExpression, Expression.Constant(request.GetStaticInjectionContext()), expression)); } }
private IActivationExpressionResult GetExpressionFromDependentStrategy(IInjectionScope scope, IActivationExpressionRequest request) { var newRequest = request.NewRequest(_dependentStrategy.ActivationType, this, request.InjectedType, request.RequestType, request.Info, true, true); var instanceResult = _dependentStrategy.GetActivationExpression(scope, newRequest); Expression propertyExpression; try { propertyExpression = Expression.PropertyOrField(instanceResult.Expression, _propertyOrFieldName); } catch (Exception exp) { throw new LocateException(request.GetStaticInjectionContext(), exp, $"Could not create property/field expression for {_propertyOrFieldName} on type {instanceResult.Expression.Type.FullName}"); } var expressionResult = request.Services.Compiler.CreateNewResult(request, propertyExpression); expressionResult.AddExpressionResult(instanceResult); return(expressionResult); }
/// <summary> /// Provide an expression that uses the lifestyle /// </summary> /// <param name="scope">scope for the strategy</param> /// <param name="request">activation request</param> /// <param name="activationExpression">expression to create strategy type</param> /// <returns></returns> public IActivationExpressionResult ProvideLifestyleExpression(IInjectionScope scope, IActivationExpressionRequest request, Func <IActivationExpressionRequest, IActivationExpressionResult> activationExpression) { if (CompiledDelegate == null) { // new request as we don't want to carry any info over from parent request var newRequest = request.NewRootedRequest(request.ActivationType, scope, true); var localDelegate = request.Services.Compiler.CompileDelegate(scope, activationExpression(newRequest)); Interlocked.CompareExchange(ref CompiledDelegate, localDelegate, null); } var getValueFromScopeMethod = typeof(SingletonPerNamedScopeLifestyle).GetRuntimeMethod("GetValueFromScope", new[] { typeof(IExportLocatorScope), typeof(ActivationStrategyDelegate), typeof(string), typeof(string), typeof(StaticInjectionContext) }); var closedMethod = getValueFromScopeMethod.MakeGenericMethod(request.ActivationType); var expression = Expression.Call(closedMethod, request.Constants.ScopeParameter, Expression.Constant(CompiledDelegate), Expression.Constant(UniqueId), Expression.Constant(_scopeName), Expression.Constant(request.GetStaticInjectionContext())); return(request.Services.Compiler.CreateNewResult(request, expression)); }
/// <summary> /// Provide linq expression for the missing dependency /// </summary> /// <param name="scope"></param> /// <param name="request"></param> /// <returns>return expression or null if it's not possible</returns> public IActivationExpressionResult ProvideExpression(IInjectionScope scope, IActivationExpressionRequest request) { var valueProvider = scope.ScopeConfiguration.Implementation.Locate <IInjectionContextValueProvider>(); var key = request.LocateKey; if (key is string) { key = ((string)key).ToLowerInvariant(); } var locateFromChildMethod = GetType().GetTypeInfo().GetDeclaredMethod("LocateFromChildContainer"); Expression expression = Expression.Call(Expression.Constant(this), locateFromChildMethod, Expression.Constant(valueProvider), request.ScopeParameter, Expression.Constant(request.GetStaticInjectionContext()), Expression.Constant(request.ActivationType), Expression.Constant(key), request.Constants.InjectionContextParameter, Expression.Constant(request.DefaultValue?.DefaultValue), Expression.Constant(request.DefaultValue != null), Expression.Constant(request.IsRequired)); expression = Expression.Convert(expression, request.ActivationType); var result = request.Services.Compiler.CreateNewResult(request, expression); result.UsingFallbackExpression = true; return(result); }
/// <summary> /// Get an activation expression for this strategy /// </summary> /// <param name="scope"></param> /// <param name="request"></param> /// <returns></returns> public override IActivationExpressionResult GetActivationExpression(IInjectionScope scope, IActivationExpressionRequest request) { var closedClass = typeof(LazyExpression <,>).MakeGenericType(request.ActivationType.GenericTypeArguments); var closedMethod = closedClass.GetRuntimeMethod("CreateLazy", new[] { typeof(IExportLocatorScope), typeof(IDisposalScope), typeof(IInjectionContext) }); var wrappedStrategy = request.GetWrappedStrategy(); if (wrappedStrategy == null) { throw new LocateException(request.GetStaticInjectionContext(), "Could not find strategy that is wrapped"); } var metadata = _strongMetadataInstanceProvider.GetMetadata(request.ActivationType.GenericTypeArguments[1], wrappedStrategy.Metadata); var instance = Activator.CreateInstance(closedClass, scope, request, this, metadata); var callExpression = Expression.Call(Expression.Constant(instance), closedMethod, request.Constants.ScopeParameter, request.DisposalScopeExpression, request.Constants.InjectionContextParameter); request.RequireInjectionContext(); return(request.Services.Compiler.CreateNewResult(request, callExpression)); }
private IActivationExpressionResult CreateTimedCreateExpression(IInjectionScope scope, IActivationExpressionRequest request, TypeActivationConfiguration activationConfiguration, IActivationExpressionResult expression) { var result = request.Services.Compiler.CreateNewResult(request); var returnVar = Expression.Variable(typeof(object)); var staticContext = request.GetStaticInjectionContext(); var callExpression = Expression.Call(Expression.Constant(this), PreBuildUpMethodInfo, Expression.Constant(staticContext), request.Constants.ScopeParameter, request.InjectionContextParameter); result.AddExtraParameter(returnVar); result.AddExtraExpression(Expression.Assign(returnVar, callExpression)); result.AddExtraExpression( Expression.IfThen(Expression.Equal(returnVar, Expression.Constant(null, typeof(object))), Expression.Assign(returnVar, expression.Expression))); result.Expression = Expression.Call(Expression.Constant(this), PostBuildUpMethodInfo, returnVar, Expression.Constant(staticContext), request.ScopeParameter, request.InjectionContextParameter); return(result); }
/// <summary> /// Select the best strategy from collection to satisfy request /// </summary> /// <param name="collection"></param> /// <param name="scope"></param> /// <param name="request"></param> /// <returns></returns> protected virtual IActivationExpressionResult SelectStrategyFromCollection(IActivationStrategyCollection <ICompiledExportStrategy> collection, IInjectionScope scope, IActivationExpressionRequest request) { var filter = request.Filter; IActivationExpressionResult result = null; foreach (var strategy in collection.GetStrategies()) { if (filter != null && !filter(strategy)) { continue; } if (strategy.HasConditions) { var context = request.GetStaticInjectionContext(); if (!strategy.Conditions.All(condition => condition.MeetsCondition(strategy, context))) { continue; } } result = strategy.GetActivationExpression(scope, request); if (result != null) { break; } } return(result); }
/// <summary> /// Creates expression for calling method GetValueFromInjectionContext /// </summary> /// <param name="scope"></param> /// <param name="request"></param> /// <returns></returns> public virtual IActivationExpressionResult GetValueFromInjectionContext(IInjectionScope scope, IActivationExpressionRequest request) { var valueMethod = typeof(ActivationExpressionBuilder).GetRuntimeMethod("GetValueFromInjectionContext", new[] { typeof(IExportLocatorScope), typeof(StaticInjectionContext), typeof(object), typeof(IInjectionContext), typeof(object), typeof(bool), typeof(bool) }); var closedMethod = valueMethod.MakeGenericMethod(request.ActivationType); var key = request.LocateKey; if (key is string) { key = ((string)key).ToLowerInvariant(); } var expresion = Expression.Call(closedMethod, request.Constants.ScopeParameter, Expression.Constant(request.GetStaticInjectionContext()), Expression.Constant(key, typeof(object)), request.Constants.InjectionContextParameter, Expression.Constant(request.DefaultValue?.DefaultValue, typeof(object)), Expression.Constant(request.DefaultValue != null), Expression.Constant(request.IsRequired)); return(request.Services.Compiler.CreateNewResult(request, expresion)); }
/// <summary> /// Get wrappers for a request /// </summary> /// <param name="scope"></param> /// <param name="type"></param> /// <param name="request"></param> /// <param name="wrappedType"></param> /// <returns></returns> public ImmutableLinkedList <IActivationPathNode> GetWrappers(IInjectionScope scope, Type type, IActivationExpressionRequest request, out Type wrappedType) { var wrapperCollection = scope.WrapperCollectionContainer.GetActivationStrategyCollection(type); if (wrapperCollection == null && type.IsConstructedGenericType) { var genericType = type.GetGenericTypeDefinition(); wrapperCollection = scope.WrapperCollectionContainer.GetActivationStrategyCollection(genericType); } if (wrapperCollection != null) { var strategy = request.Filter == null?wrapperCollection.GetPrimary() : null; if (strategy == null) { foreach (var s in wrapperCollection.GetStrategies()) { var pass = true; if (s.HasConditions) { foreach (var condition in s.Conditions) { if (!condition.MeetsCondition(s, request.GetStaticInjectionContext())) { pass = false; } } } if (pass) { strategy = s; break; } } } if (strategy != null) { var newType = strategy.GetWrappedType(type); if (newType == null) { throw new Exception("Wrapper strategy returned null for wrapped type, " + strategy.GetType().FullName); } return(GetWrappers(scope, newType, request, out wrappedType).Add(new WrapperActivationPathNode(strategy, type, null))); } } wrappedType = type; return(ImmutableLinkedList <IActivationPathNode> .Empty); }
/// <summary> /// Applies null check and disposal scope tracking logic to an expression /// </summary> /// <param name="scope"></param> /// <param name="request"></param> /// <param name="expression"></param> /// <param name="allowDisposableTracking"></param> /// <returns></returns> public static Expression ApplyNullCheckAndAddDisposal(IInjectionScope scope, IActivationExpressionRequest request, Expression expression, bool allowDisposableTracking) { if (expression.Type != request.ActivationType && !ReflectionService.CheckTypeIsBasedOnAnotherType(expression.Type, request.ActivationType)) { expression = Expression.Convert(expression, request.ActivationType); } if (!allowDisposableTracking) { if (!scope.ScopeConfiguration.Behaviors.AllowInstanceAndFactoryToReturnNull) { var closedMethod = CheckForNullMethodInfo.MakeGenericMethod(request.ActivationType); return(Expression.Call(closedMethod, Expression.Constant(request.GetStaticInjectionContext()), expression)); } } else { if (scope.ScopeConfiguration.Behaviors.AllowInstanceAndFactoryToReturnNull) { var closedMethod = AddToDisposalScopeMethodInfo.MakeGenericMethod(request.ActivationType); return(Expression.Call(closedMethod, request.DisposalScopeExpression, expression)); } else { var closedMethod = CheckForNullAndAddToDisposalScopeMethodInfo.MakeGenericMethod(request.ActivationType); return(Expression.Call(closedMethod, request.DisposalScopeExpression, Expression.Constant(request.GetStaticInjectionContext()), expression)); } } return(expression); }
private IActivationExpressionResult CreateExpressionResultFromBindingAttribute(IInjectionScope scope, IActivationExpressionRequest request, object cacheKey, string name, Type modelType, IEnumerable <object> attributes) { var closedType = typeof(BindingSourceHelper <>).MakeGenericType(modelType); if (_modelBinderFactory == null) { scope.TryLocate(out _modelBinderFactory); } if (_modelMetadataProvider == null) { scope.TryLocate(out _modelMetadataProvider); } if (_factories == null) { if (scope.TryLocate(out IOptions <MvcOptions> optionsAccessor)) { _factories = optionsAccessor.Value.ValueProviderFactories.ToArray(); } } if (_modelBinderFactory != null && _modelMetadataProvider != null && _factories != null) { var defaultValue = request.DefaultValue?.DefaultValue; var instance = Activator.CreateInstance(closedType, _factories, name, attributes, defaultValue, request.GetStaticInjectionContext()); var closedMethod = closedType.GetRuntimeMethod("GetValue", new[] { typeof(IExportLocatorScope) }); var expression = Expression.Call(Expression.Constant(instance), closedMethod, request.Constants.ScopeParameter); return(request.Services.Compiler.CreateNewResult(request, expression)); } return(null); }
/// <summary> /// Provide an expression that uses the lifestyle /// </summary> /// <param name="scope">scope for the strategy</param> /// <param name="request">activation request</param> /// <param name="activationExpression">expression to create strategy type</param> /// <returns></returns> public IActivationExpressionResult ProvideLifestyleExpression(IInjectionScope scope, IActivationExpressionRequest request, Func <IActivationExpressionRequest, IActivationExpressionResult> activationExpression) { var context = request.GetStaticInjectionContext(); var ancestorId = GetAncestorRequestId(context); var newDelegate = request.Services.Compiler.CompileDelegate(scope, activationExpression(request)); MethodInfo closedMethod; if (_guaranteeOnlyOne) { var openMethod = typeof(SingletonPerAncestor).GetRuntimeMethod(nameof(GetValueGuaranteeOnce), new[] { typeof(IExportLocatorScope), typeof(IDisposalScope), typeof(IInjectionContext), typeof(ActivationStrategyDelegate), typeof(string) }); closedMethod = openMethod.MakeGenericMethod(request.ActivationType); } else { var openMethod = typeof(SingletonPerAncestor).GetRuntimeMethod(nameof(GetValue), new[] { typeof(IExportLocatorScope), typeof(IDisposalScope), typeof(IInjectionContext), typeof(ActivationStrategyDelegate), typeof(string) }); closedMethod = openMethod.MakeGenericMethod(request.ActivationType); } var expression = Expression.Call(closedMethod, request.ScopeParameter, request.DisposalScopeExpression, request.InjectionContextParameter, Expression.Constant(newDelegate), Expression.Constant(ancestorId)); request.RequireInjectionContext(); request.RequireExportScope(); return(request.Services.Compiler.CreateNewResult(request, expression)); }
/// <summary> /// Get expression from an activation strategy collection /// </summary> /// <param name="scope"></param> /// <param name="arrayElementType"></param> /// <param name="request"></param> /// <param name="expressions"></param> /// <param name="collection"></param> /// <param name="wrappedType"></param> /// <param name="wrappers"></param> public static void GetExpressionFromCollection(IInjectionScope scope, Type arrayElementType, IActivationExpressionRequest request, List <IActivationExpressionResult> expressions, IActivationStrategyCollection <ICompiledExportStrategy> collection, Type wrappedType, ImmutableLinkedList <IActivationPathNode> wrappers) { foreach (var strategy in collection.GetStrategies()) { if (strategy.HasConditions) { var staticContext = request.GetStaticInjectionContext(); var pass = true; foreach (var condition in strategy.Conditions) { if (!condition.MeetsCondition(strategy, staticContext)) { pass = false; break; } } if (!pass) { continue; } } var newRequest = request.NewRequest(arrayElementType, request.RequestingStrategy, request.RequestingStrategy?.ActivationType, RequestType.Other, null, true); var newPath = ImmutableLinkedList <IActivationPathNode> .Empty.Add( new WrapperActivationPathNode(strategy, wrappedType, null)).AddRange(wrappers); newRequest.SetWrapperPath(newPath); var wrapper = newRequest.PopWrapperPathNode(); expressions.Add(wrapper.GetActivationExpression(scope, newRequest)); } }
/// <summary> /// Creates expression for calling method GetValueFromInjectionContext /// </summary> /// <param name="scope"></param> /// <param name="request"></param> /// <returns></returns> public virtual IActivationExpressionResult GetValueFromInjectionContext(IInjectionScope scope, IActivationExpressionRequest request) { var valueMethod = _contextValueProvider.GetType().GetRuntimeMethod(nameof(GetValueFromInjectionContext), new[] { typeof(IExportLocatorScope), typeof(StaticInjectionContext), typeof(object), typeof(IInjectionContext), typeof(object), typeof(bool), typeof(bool) }); var closedMethod = valueMethod.MakeGenericMethod(request.ActivationType); var key = request.LocateKey; if (key is string) { key = ((string)key).ToLowerInvariant(); } request.RequireExportScope(); var expression = Expression.Call(Expression.Constant(_contextValueProvider), closedMethod, request.ScopeParameter, Expression.Constant(request.GetStaticInjectionContext()), Expression.Constant(key, typeof(object)), request.InjectionContextParameter, Expression.Constant(request.DefaultValue?.DefaultValue, typeof(object)), Expression.Constant(request.DefaultValue != null), Expression.Constant(request.IsRequired)); var result = request.Services.Compiler.CreateNewResult(request, expression); result.UsingFallbackExpression = true; return(result); }
/// <summary> /// Creates member injection statements /// </summary> /// <param name="scope"></param> /// <param name="request"></param> /// <param name="activationConfiguration"></param> /// <param name="result"></param> /// <returns></returns> protected virtual IActivationExpressionResult CreateMemberInjectExpressions(IInjectionScope scope, IActivationExpressionRequest request, TypeActivationConfiguration activationConfiguration, IActivationExpressionResult result) { var members = GetMemberInjectionInfoForConfiguration(scope, request, activationConfiguration); if (members.Count == 0) { return(result); } ParameterExpression variable = result.Expression as ParameterExpression; var newResult = request.Services.Compiler.CreateNewResult(request); if (variable == null) { variable = Expression.Variable(result.Expression.Type); newResult.AddExpressionResult(result); newResult.AddExtraParameter(variable); newResult.AddExtraExpression(Expression.Assign(variable, result.Expression)); } foreach (var memberKVP in members) { var expression = memberKVP.Value.CreateExpression; if (expression == null) { var memberType = memberKVP.Key.GetMemeberType(); var newRequest = request.NewRequest(memberType, activationConfiguration.ActivationStrategy, activationConfiguration.ActivationType, RequestType.Member, memberKVP.Key, false, true); if (memberKVP.Value.LocateKey == null && scope.ScopeConfiguration.Behaviors.KeyedTypeSelector(memberType)) { newRequest.SetLocateKey(memberKVP.Key.Name); } else { newRequest.SetLocateKey(memberKVP.Value.LocateKey); } newRequest.IsDynamic = memberKVP.Value.IsDynamic; newRequest.SetIsRequired(memberKVP.Value.IsRequired); newRequest.SetFilter(memberKVP.Value.Filter); if (memberKVP.Value.DefaultValue != null) { newRequest.SetDefaultValue( new DefaultValueInformation { DefaultValue = memberKVP.Value.DefaultValue }); } var memberResult = request.Services.ExpressionBuilder.GetActivationExpression(scope, newRequest); if (memberResult == null) { if (memberKVP.Value.IsRequired) { throw new LocateException(newRequest.GetStaticInjectionContext()); } } else { Expression memberExpression; if (memberKVP.Key is FieldInfo) { memberExpression = Expression.Field(variable, memberKVP.Key as FieldInfo); } else if (memberKVP.Key is PropertyInfo) { memberExpression = Expression.Property(variable, (PropertyInfo)memberKVP.Key); } else { throw new LocateException(request.GetStaticInjectionContext(), $"{memberKVP.Key.GetType().Name} member type not supported"); } newResult.AddExpressionResult(memberResult); newResult.AddExtraExpression(Expression.Assign(memberExpression, memberResult.Expression)); } } else { Expression memberExpression; if (memberKVP.Key is FieldInfo) { memberExpression = Expression.Field(variable, memberKVP.Key as FieldInfo); } else if (memberKVP.Key is PropertyInfo) { memberExpression = Expression.Property(variable, (PropertyInfo)memberKVP.Key); } else { throw new LocateException(request.GetStaticInjectionContext(), $"{memberKVP.Key.GetType().Name} member type not supported"); } newResult.AddExtraExpression(Expression.Assign(memberExpression, expression)); } } newResult.Expression = variable; return(newResult); }
private IActivationExpressionResult BuildActivationExpression(IInjectionScope scope, IActivationExpressionRequest request, TypeActivationConfiguration activationConfiguration) { var returnLabel = Expression.Label(typeof(object)); var variables = new List <ParameterExpression>(); var testVariableExpressions = new List <Expression>(); var testExpressions = new List <Expression>(); var foundValues = new Dictionary <string, Tuple <ParameterExpression, string> >(); var throwAtEnd = true; foreach (var constructorInfo in GetConstructors(activationConfiguration.ActivationType)) { var testParameters = new List <ParameterExpression>(); var locateParameters = new List <Expression>(); foreach (var parameter in constructorInfo.GetParameters()) { var paramKey = parameter.Name + "|" + parameter.ParameterType.FullName; Tuple <ParameterExpression, string> parameterExpression; if (!foundValues.TryGetValue(paramKey, out parameterExpression)) { var canLocateInfo = CreateCanLocateStatement(parameter, scope, request, activationConfiguration); // only test for required parameters with no default value if (canLocateInfo != null) { parameterExpression = new Tuple <ParameterExpression, string>(canLocateInfo.Item1, $"{parameter.ParameterType.Name} {parameter.Name}"); foundValues.Add(paramKey, parameterExpression); variables.Add(parameterExpression.Item1); testVariableExpressions.Add(canLocateInfo.Item2); } } if (parameterExpression != null) { testParameters.Add(parameterExpression.Item1); } locateParameters.Add(CreateLocateExpression(parameter, scope, request, activationConfiguration)); } var newValue = Expression.Return(returnLabel, Expression.New(constructorInfo, locateParameters)); if (testParameters.Count > 0) { if (testParameters.Count == 1) { testExpressions.Add(Expression.IfThen(Expression.IsTrue(testParameters[0]), newValue)); } else { var andExpression = Expression.And(testParameters[0], testParameters[1]); for (int i = 2; i < testParameters.Count; i++) { andExpression = Expression.And(andExpression, testParameters[i]); } testExpressions.Add(Expression.IfThen(andExpression, newValue)); } } else { testExpressions.Add(newValue); throwAtEnd = false; break; } } if (throwAtEnd) { var constructor = typeof(LocateException).GetTypeInfo() .DeclaredConstructors.Single(c => c.GetParameters().Length == 2); var testValues = foundValues.Values.ToArray(); var foundArrayExpression = Expression.NewArrayInit(typeof(bool), testValues.Select(t => t.Item1)); var labelArray = Expression.Constant(testValues.Select(t => t.Item2).ToArray()); var createErrorStringMethod = typeof(DynamicConstructorExpressionCreator).GetTypeInfo() .GetDeclaredMethod("CreateMissingErrorMessage"); testExpressions.Add(Expression.Throw(Expression.New(constructor, Expression.Constant(request.GetStaticInjectionContext()), Expression.Call(createErrorStringMethod, foundArrayExpression, labelArray)))); } var result = request.Services.Compiler.CreateNewResult(request, Expression.Label(returnLabel, Expression.Default(request.ActivationType))); foreach (var variable in variables) { result.AddExtraParameter(variable); } foreach (var expression in testVariableExpressions) { result.AddExtraExpression(expression); } foreach (var expression in testExpressions) { result.AddExtraExpression(expression); } return(result); }
/// <summary> /// Get expression result from request /// </summary> /// <param name="scope"></param> /// <param name="request"></param> /// <param name="activationType"></param> /// <param name="key"></param> /// <returns></returns> protected virtual IActivationExpressionResult GetValueFromRequest(IInjectionScope scope, IActivationExpressionRequest request, Type activationType, object key) { var knownValues = request.KnownValueExpressions.Where( v => activationType.GetTypeInfo().IsAssignableFrom(v.ActivationType.GetTypeInfo())).ToArray(); if (knownValues.Length > 0) { if (knownValues.Length == 1) { return(knownValues[0].ValueExpression(request)); } if (key != null) { IKnownValueExpression knownValue; if (key is string keyString) { knownValue = knownValues.FirstOrDefault(v => string.Compare(keyString, v.Key as string, StringComparison.CurrentCultureIgnoreCase) == 0); } else { knownValue = knownValues.FirstOrDefault(v => v.Key == key); } if (knownValue != null) { return(knownValue.ValueExpression(request)); } } if (request.Info is MemberInfo memberInfo) { var knownValue = knownValues.FirstOrDefault(v => Equals(v.Key, memberInfo.Name)); if (knownValue != null) { return(knownValue.ValueExpression(request)); } } if (request.Info is ParameterInfo parameterInfo) { var knownValue = knownValues.FirstOrDefault(v => Equals(v.Key, parameterInfo.Name)); if (knownValue != null) { return(knownValue.ValueExpression(request)); } knownValue = knownValues.FirstOrDefault(v => Equals(v.Position.GetValueOrDefault(-1), parameterInfo.Position)); if (knownValue != null) { return(knownValue.ValueExpression(request)); } } return(knownValues[0].ValueExpression(request)); } if (request.WrapperPathNode != null) { var configuration = request.WrapperPathNode.Strategy.GetActivationConfiguration(activationType); if (activationType.GetTypeInfo().IsAssignableFrom(configuration.ActivationType.GetTypeInfo())) { var wrapper = request.PopWrapperPathNode(); return(ProcessPathNode(scope, request, activationType, wrapper)); } } else if (request.DecoratorPathNode != null) { var configuration = request.DecoratorPathNode.Strategy.GetActivationConfiguration(activationType); if (activationType.GetTypeInfo().IsAssignableFrom(configuration.ActivationType.GetTypeInfo())) { var decorator = request.PopDecoratorPathNode(); return(ProcessPathNode(scope, request, activationType, decorator)); } } if (request.ActivationType == typeof(IInjectionScope)) { if (!scope.ScopeConfiguration.Behaviors.AllowInjectionScopeLocation) { throw new ImportInjectionScopeException(request.GetStaticInjectionContext()); } var method = typeof(IExportLocatorScopeExtensions).GetRuntimeMethod("GetInjectionScope", new[] { typeof(IExportLocatorScope) }); var expression = Expression.Call(method, request.ScopeParameter); return(request.Services.Compiler.CreateNewResult(request, expression)); } if (request.ActivationType == typeof(IExportLocatorScope) || request.ActivationType == typeof(ILocatorService)) { return(request.Services.Compiler.CreateNewResult(request, request.ScopeParameter)); } if (request.ActivationType == typeof(IDisposalScope) || (request.ActivationType == typeof(IDisposable) && request.RequestingScope.ScopeConfiguration.InjectIDisposable)) { return(request.Services.Compiler.CreateNewResult(request, request.DisposalScopeExpression)); } if (request.ActivationType == typeof(IInjectionContext)) { request.RequireInjectionContext(); return(request.Services.Compiler.CreateNewResult(request, request.InjectionContextParameter)); } if (request.ActivationType == typeof(StaticInjectionContext)) { var staticContext = request.Parent != null? request.Parent.GetStaticInjectionContext() : request.GetStaticInjectionContext(); return(request.Services.Compiler.CreateNewResult(request, Expression.Constant(staticContext))); } if (request.IsDynamic) { var dynamicMethod = typeof(ActivationExpressionBuilder).GetRuntimeMethod("GetDynamicValue", new[] { typeof(IExportLocatorScope), typeof(IDisposalScope), typeof(StaticInjectionContext), typeof(IInjectionContext), typeof(object), typeof(bool), typeof(bool), typeof(object) }); var closedMethod = dynamicMethod.MakeGenericMethod(request.ActivationType); Expression defaultExpression = Expression.Constant(request.DefaultValue?.DefaultValue, typeof(object)); var expression = Expression.Call(closedMethod, request.ScopeParameter, request.DisposalScopeExpression, Expression.Constant(request.GetStaticInjectionContext()), request.InjectionContextParameter, Expression.Constant(request.LocateKey, typeof(object)), Expression.Constant(request.IsRequired), Expression.Constant(request.DefaultValue != null), defaultExpression); return(request.Services.Compiler.CreateNewResult(request, expression)); } return(null); }
/// <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 expression result from request /// </summary> /// <param name="scope"></param> /// <param name="request"></param> /// <param name="activationType"></param> /// <param name="key"></param> /// <returns></returns> protected virtual IActivationExpressionResult GetValueFromRequest(IInjectionScope scope, IActivationExpressionRequest request, Type activationType, object key) { var knownValue = request.KnownValueExpressions.FirstOrDefault( v => activationType.GetTypeInfo().IsAssignableFrom(v.ActivationType.GetTypeInfo())); if (knownValue != null) { return(knownValue.ValueExpression(request)); } if (request.WrapperPathNode != null) { var configuration = request.WrapperPathNode.Strategy.GetActivationConfiguration(activationType); if (activationType.GetTypeInfo().IsAssignableFrom(configuration.ActivationType.GetTypeInfo())) { var wrapper = request.PopWrapperPathNode(); return(ProcessPathNode(scope, request, activationType, wrapper)); } } else if (request.DecoratorPathNode != null) { var configuration = request.DecoratorPathNode.Strategy.GetActivationConfiguration(activationType); if (activationType.GetTypeInfo().IsAssignableFrom(configuration.ActivationType.GetTypeInfo())) { var decorator = request.PopDecoratorPathNode(); return(ProcessPathNode(scope, request, activationType, decorator)); } } if (request.ActivationType == typeof(IInjectionScope)) { if (!scope.ScopeConfiguration.Behaviors.AllowInjectionScopeLocation) { throw new ImportInjectionScopeException(request.GetStaticInjectionContext()); } var method = typeof(IExportLocatorScopeExtensions).GetRuntimeMethod("GetInjectionScope", new[] { typeof(IExportLocatorScope) }); var expression = Expression.Call(method, request.Constants.ScopeParameter); return(request.Services.Compiler.CreateNewResult(request, expression)); } if (request.ActivationType == typeof(IExportLocatorScope) || request.ActivationType == typeof(ILocatorService)) { return(request.Services.Compiler.CreateNewResult(request, request.Constants.ScopeParameter)); } if (request.ActivationType == typeof(IInjectionContext)) { request.RequireInjectionContext(); return(request.Services.Compiler.CreateNewResult(request, request.Constants.InjectionContextParameter)); } if (request.ActivationType == typeof(StaticInjectionContext)) { var staticContext = request.Parent != null? request.Parent.GetStaticInjectionContext() : request.GetStaticInjectionContext(); return(request.Services.Compiler.CreateNewResult(request, Expression.Constant(staticContext))); } if (request.IsDynamic) { var dynamicMethod = typeof(ActivationExpressionBuilder).GetRuntimeMethod("GetDynamicValue", new[] { typeof(IExportLocatorScope), typeof(IDisposalScope), typeof(StaticInjectionContext), typeof(IInjectionContext), typeof(object), typeof(bool), typeof(bool), typeof(object) }); var closedMethod = dynamicMethod.MakeGenericMethod(request.ActivationType); Expression defaultExpression = Expression.Constant(request.DefaultValue?.DefaultValue, typeof(object)); var expression = Expression.Call(closedMethod, request.Constants.ScopeParameter, request.DisposalScopeExpression, Expression.Constant(request.GetStaticInjectionContext()), request.Constants.InjectionContextParameter, Expression.Constant(request.LocateKey, typeof(object)), Expression.Constant(request.IsRequired), Expression.Constant(request.DefaultValue != null), defaultExpression); return(request.Services.Compiler.CreateNewResult(request, expression)); } return(null); }
/// <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); }