/// <summary> /// Get a list of dependencies for a constructor /// </summary> /// <param name="configuration"></param> /// <param name="request"></param> /// <param name="constructor"></param> /// <returns></returns> protected virtual IEnumerable <ActivationStrategyDependency> GetDependenciesForConstructor(TypeActivationConfiguration configuration, IActivationExpressionRequest request, ConstructorInfo constructor) { var dependencies = ImmutableLinkedList <ActivationStrategyDependency> .Empty; var injectionScope = request.RequestingScope; foreach (var parameter in constructor.GetParameters()) { object key = null; if (injectionScope.ScopeConfiguration.Behaviors.KeyedTypeSelector(parameter.ParameterType)) { key = parameter.Name; } var dependencySatisified = parameter.IsOptional || parameter.ParameterType.IsGenericParameter || CanGetValueFromInfo(configuration, parameter) || injectionScope.CanLocate(parameter.ParameterType, null, key); var dependency = new ActivationStrategyDependency(DependencyType.ConstructorParameter, configuration.ActivationStrategy, parameter, parameter.ParameterType, parameter.Name, false, false, dependencySatisified); dependencies = dependencies.Add(dependency); } return(dependencies); }
/// <summary> /// This method is used to pick a constructor from a type /// </summary> /// <param name="requestingScope"></param> /// <param name="configuration"></param> /// <param name="request"></param> /// <returns></returns> protected virtual ConstructorInfo PickConstructor(IInjectionScope requestingScope, TypeActivationConfiguration configuration, IActivationExpressionRequest request) { if (configuration.SelectedConstructor != null) { return(configuration.SelectedConstructor); } var constructors = configuration.ActivationType.GetTypeInfo().DeclaredConstructors.Where(c => c.IsPublic && !c.IsStatic).OrderByDescending(c => c.GetParameters().Length).ToArray(); if (constructors.Length == 0) { throw new Exception("Could not find public constructor on type " + configuration.ActivationType.FullName); } if (constructors.Length == 1) { return(constructors[0]); } return(PickConstructor(requestingScope, configuration, request, constructors)); }
/// <summary> /// This method is called when there are multiple constructors /// </summary> /// <param name="injectionScope"></param> /// <param name="configuration"></param> /// <param name="request"></param> /// <param name="constructors"></param> /// <returns></returns> protected abstract ConstructorInfo PickConstructor(IInjectionScope injectionScope, TypeActivationConfiguration configuration, IActivationExpressionRequest request, ConstructorInfo[] constructors);
/// <summary> /// Get expression for parameter /// </summary> /// <param name="parameter"></param> /// <param name="parameterInfo"></param> /// <param name="injectionScope"></param> /// <param name="configuration"></param> /// <param name="request"></param> /// <returns></returns> protected virtual IActivationExpressionResult GetParameterExpression(ParameterInfo parameter, ConstructorParameterInfo parameterInfo, IInjectionScope injectionScope, TypeActivationConfiguration configuration, IActivationExpressionRequest request, out IActivationExpressionRequest newRequest) { if (parameterInfo?.ExportFunc != null) { newRequest = null; return(CallExportFunc(configuration.ActivationStrategy, parameter, parameterInfo, injectionScope, request, configuration.ExternallyOwned)); } newRequest = request.NewRequest(parameterInfo?.UseType ?? parameter.ParameterType, configuration.ActivationStrategy, configuration.ActivationType, RequestType.ConstructorParameter, parameter, true, true); if (parameterInfo?.LocateWithKey != null) { newRequest.SetLocateKey(parameterInfo.LocateWithKey); } else if (injectionScope.ScopeConfiguration.Behaviors.KeyedTypeSelector(parameter.ParameterType)) { newRequest.SetLocateKey(parameter.Name); } SetDefaultValue(parameter, parameterInfo, newRequest); if (parameterInfo != null) { newRequest.IsDynamic = parameterInfo.IsDynamic; newRequest.SetIsRequired(parameterInfo.IsRequired.GetValueOrDefault(!parameter.IsOptional)); newRequest.SetFilter(parameterInfo.ExportStrategyFilter); newRequest.SetEnumerableComparer(parameterInfo.EnumerableComparer); } else { newRequest.SetIsRequired(!parameter.IsOptional); } return(newRequest.Services.ExpressionBuilder.GetActivationExpression(injectionScope, newRequest)); }
/// <summary> /// Create expression to call func /// </summary> /// <param name="strategy"></param> /// <param name="parameter"></param> /// <param name="parameterInfo"></param> /// <param name="injectionScope"></param> /// <param name="request"></param> /// <param name="configurationExternallyOwned"></param> /// <returns></returns> protected IActivationExpressionResult CallExportFunc(IActivationStrategy strategy, ParameterInfo parameter, ConstructorParameterInfo parameterInfo, IInjectionScope injectionScope, IActivationExpressionRequest request, bool configurationExternallyOwned) { var exportDelegate = parameterInfo.ExportFunc as Delegate; if (exportDelegate == null) { throw new ArgumentException($"Parameter Info {parameterInfo.ParameterName} is not delegate", nameof(parameterInfo)); } var newRequest = request.NewRequest(parameter.ParameterType, strategy, strategy.ActivationType, RequestType.ConstructorParameter, parameter, false, true); return(ExpressionUtilities.CreateExpressionForDelegate(exportDelegate, ShouldTrackDisposable(configurationExternallyOwned, injectionScope, strategy), injectionScope, newRequest, strategy)); }
/// <summary> /// Get Methods to inject /// </summary> /// <param name="type">type being activated</param> /// <param name="injectionScope">injection scope</param> /// <param name="request">request</param> /// <returns>methods being injected</returns> public IEnumerable <MethodInjectionInfo> GetMethods(Type type, IInjectionScope injectionScope, IActivationExpressionRequest request) { yield break; }
/// <summary> /// Allow constructor selector to override method /// </summary> /// <param name="injectionScope"></param> /// <param name="configuration"></param> /// <param name="request"></param> /// <param name="constructor"></param> /// <param name="expression"></param> /// <returns></returns> protected virtual IActivationExpressionResult OverrideExpression(IInjectionScope injectionScope, TypeActivationConfiguration configuration, IActivationExpressionRequest request, ConstructorInfo constructor, IActivationExpressionResult expression) { return(expression); }
/// <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> /// Get a list of member injection info for a specific type /// </summary> /// <param name="type">type being activated</param> /// <param name="injectionScope">injection scope</param> /// <param name="request">request</param> /// <returns>members being injected</returns> public IEnumerable <MemberInjectionInfo> GetPropertiesAndFields(Type type, IInjectionScope injectionScope, IActivationExpressionRequest request) { foreach (var property in type.GetRuntimeProperties()) { if (!property.CanWrite || !property.SetMethod.IsPublic || property.SetMethod.IsStatic) { continue; } if (ReflectionService.CheckTypeIsBasedOnAnotherType(property.PropertyType, _memberType)) { if (_filter == null || _filter(property)) { yield return(new MemberInjectionInfo { MemberInfo = property, LocateKey = LocateKey, IsRequired = IsRequired }); } } } foreach (var field in type.GetRuntimeFields()) { if (!field.IsPublic || field.IsStatic) { continue; } if (ReflectionService.CheckTypeIsBasedOnAnotherType(field.FieldType, _memberType)) { if (_filter == null || _filter(field)) { yield return(new MemberInjectionInfo { MemberInfo = field, LocateKey = LocateKey, IsRequired = IsRequired }); } } } }
/// <summary> /// Create expression that is implemented in child class /// </summary> /// <param name="scope"></param> /// <param name="request"></param> /// <param name="lifestyle"></param> /// <returns></returns> protected override IActivationExpressionResult CreateExpression(IInjectionScope scope, IActivationExpressionRequest request, ICompiledLifestyle lifestyle) { if (lifestyle == null) { return(CreateExpression(scope, request)); } return(lifestyle.ProvideLifestyleExpression(scope, request, expressionRequest => CreateExpression(scope, expressionRequest))); }
/// <summary> /// Create expression that calls a delegate /// </summary> /// <param name="scope">scope for the request</param> /// <param name="request">activation request</param> /// <returns></returns> protected virtual IActivationExpressionResult CreateExpression(IInjectionScope scope, IActivationExpressionRequest request) { return(ExpressionUtilities.CreateExpressionForDelegate(DelegateInstance, ShouldTrackDisposable(scope), scope, request)); }
/// <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 invokeMethod = request.ActivationType.GetTypeInfo().GetDeclaredMethod("Invoke"); var list = new List <Type>(invokeMethod.GetParameters().Select(p => p.ParameterType)); list.Add(invokeMethod.ReturnType); list.Add(request.ActivationType); var closedClass = typeof(DelegateExpression <, , ,>).MakeGenericType(list.ToArray()); var closedMethod = closedClass.GetRuntimeMethod("CreateDelegate", new[] { typeof(IExportLocatorScope), typeof(IDisposalScope), typeof(IInjectionContext) }); var instance = Activator.CreateInstance(closedClass, scope, request, request.Services.InjectionContextCreator, this); var callExpression = Expression.Call(Expression.Constant(instance), closedMethod, request.Constants.ScopeParameter, request.DisposalScopeExpression, request.Constants.InjectionContextParameter); 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 abstract IActivationExpressionResult GetActivationExpression(IInjectionScope scope, IActivationExpressionRequest request);
/// <summary> /// Get an activation expression for this strategy /// </summary> /// <param name="scope"></param> /// <param name="request"></param> /// <param name="lifestyle"></param> /// <returns></returns> public abstract IActivationExpressionResult GetDecoratorActivationExpression(IInjectionScope scope, IActivationExpressionRequest request, ICompiledLifestyle lifestyle);
/// <summary> /// Default constructor /// </summary> /// <param name="scope"></param> /// <param name="request"></param> /// <param name="activationStrategy"></param> public LazyExpression(IInjectionScope scope, IActivationExpressionRequest request, IActivationStrategy activationStrategy) { _scope = scope; _request = request; _activationStrategy = activationStrategy; }
/// <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(nameof(LazyExpression <object> .CreateLazy), new[] { typeof(IExportLocatorScope), typeof(IDisposalScope), typeof(IInjectionContext) }); var instance = Activator.CreateInstance(closedClass, scope, request, this); request.RequireExportScope(); request.RequireDisposalScope(); var callExpression = Expression.Call(Expression.Constant(instance), closedMethod, request.ScopeParameter, request.DisposalScopeExpression, request.InjectionContextParameter); request.RequireInjectionContext(); return(request.Services.Compiler.CreateNewResult(request, callExpression)); }