/// <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)); }
/// <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 instance = Activator.CreateInstance(closedClass, scope, request, this); 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)); }
/// <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 an activation expression for this strategy /// </summary> /// <param name="scope">IInjectionScope</param> /// <param name="request">IActivationExpressionRequest</param> /// <returns>IActivationExpressionResult</returns> public override IActivationExpressionResult GetActivationExpression( IInjectionScope scope, IActivationExpressionRequest request) { var activationDelegate = CompileDelegate(scope, request); var factory = typeof(GraceOptionalFactory <>) .MakeGenericType(request.ActivationType.GenericTypeArguments[0]) .GetConstructors() .First() .Invoke(new object[] { activationDelegate, request.LocateKey }); var callExpression = Expression.Call( Expression.Constant(factory), factory.GetType().GetMethod(nameof(GraceOptionalFactory <object> .CreateOptional)), request.ScopeParameter, request.DisposalScopeExpression, request.InjectionContextParameter); request.RequireInjectionContext(); return(request.Services.Compiler.CreateNewResult(request, callExpression)); }
public IActivationExpressionResult ProvideLifestyleExpression(IInjectionScope scope, IActivationExpressionRequest request, Func <IActivationExpressionRequest, IActivationExpressionResult> activationExpression) { request.RequireInjectionContext(); if (ConstantExpression != null) { return(request.Services.Compiler.CreateNewResult(request, ConstantExpression)); } // Create new request as we shouldn't carry over anything from the previous request var newRequest = request.NewRootedRequest(request.ActivationType, scope, true); _activationDelegate = request.Services.Compiler.CompileDelegate(scope, activationExpression(newRequest)); ConstantExpression = Expression.Convert(Expression.Call(Expression.Constant(this), getInstanceMethodInfo, newRequest.ScopeParameter, Expression.Constant(scope), request.InjectionContextParameter, Expression.Constant(_activationDelegate)), request.ActivationType); var result = request.Services.Compiler.CreateNewResult(request, ConstantExpression); return(result); }
/// <inheritdoc /> protected override IActivationExpressionResult CreateExpression(IInjectionScope scope, IActivationExpressionRequest request, ICompiledLifestyle lifestyle) { if (_proxyType == null) { lock (_proxyTypeLock) { if (_proxyType == null) { var builder = new DynamicTypeBuilder(); _proxyType = builder.CreateType(ActivationType, out _delegateInfo); } } } request.RequireExportScope(); request.RequireDisposalScope(); request.RequireInjectionContext(); var parameters = new List <Expression> { request.ScopeParameter, request.DisposalScopeExpression, request.InjectionContextParameter }; var uniqueId = UniqueStringId.Generate(); foreach (var delegateInfo in _delegateInfo) { var locateType = delegateInfo.Method.ReturnType; var newRequest = request.NewRequest(locateType, this, ActivationType, RequestType.Other, null, true); newRequest.AddKnownValueExpression( CreateKnownValueExpression(newRequest, ActivationType, uniqueId)); if (delegateInfo.Method.Name.StartsWith("Get")) { newRequest.SetLocateKey(delegateInfo.Method.Name.Substring("Get".Length)); } if (delegateInfo.ParameterInfos != null) { foreach (var parameter in delegateInfo.ParameterInfos) { newRequest.AddKnownValueExpression( CreateKnownValueExpression(newRequest, parameter.ParameterInfo.ParameterType, parameter.UniqueId, parameter.ParameterInfo.Name, parameter.ParameterInfo.Position)); } } var result = request.Services.ExpressionBuilder.GetActivationExpression(request.RequestingScope, newRequest); var compiledDelegate = request.Services.Compiler.CompileDelegate(request.RequestingScope, result); parameters.Add(Expression.Constant(compiledDelegate)); } var constructor = _proxyType.GetTypeInfo().DeclaredConstructors.First(); request.RequireInjectionContext(); var newStatement = Expression.New(constructor, parameters); var setMethod = typeof(IExtraDataContainer).GetRuntimeMethod(nameof(IExtraDataContainer.SetExtraData), new[] { typeof(object), typeof(object), typeof(bool) }); var invokeStatement = Expression.Call(request.InjectionContextParameter, setMethod, Expression.Constant(uniqueId), newStatement, Expression.Constant(true)); var castStatement = Expression.Convert(invokeStatement, ActivationType); return(request.Services.Compiler.CreateNewResult(request, castStatement)); }
/// <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 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); }