public static bool TryInject( IServiceRegistrationProvider serviceProvider, object target, Type attributeType, ITrace logger = null, Func <Type, object> instanceProvider = null, bool tryConstructArguments = false, bool?requireConstructorAttributes = null, IReadOnlyCollection <Type> constructorAttributeTypes = null) { if (serviceProvider == null) { throw new ArgumentNullException(nameof(serviceProvider)); } if (target == null) { throw new ArgumentNullException(nameof(target)); } if (attributeType == null) { throw new ArgumentNullException(nameof(attributeType)); } if ((constructorAttributeTypes == null) || (constructorAttributeTypes.Count == 0)) { constructorAttributeTypes = new[] { typeof(ServiceProviderConstructorAttribute) } } ; ServiceConstructorRequest request = new ServiceConstructorRequest(logger ?? TraceSources.For(typeof(ServiceConstructorMethods))); request.Logger.Verbose( "Injecting '{0}' on '{1}'.", attributeType.GetFriendlyFullName(), target.GetType().GetFriendlyFullName()); if (ServiceConstructorMethods.invokeMember( ServiceConstructorMethods.findMethods(target, attributeType, request.TraceStack), true, target, out _, request, serviceProvider, instanceProvider, tryConstructArguments, requireConstructorAttributes, constructorAttributeTypes, false)) { request.Logger.Verbose( "Inject result for '{0}' on '{1}' is true.", attributeType.GetFriendlyFullName(), target.GetType().GetFriendlyFullName()); return(true); } request.Logger.Info( "Inject result for '{0}' on '{1}' is false.", attributeType.GetFriendlyFullName(), target.GetType().GetFriendlyFullName()); return(false); }
/// <summary> /// Utility method resolves the type and logs and returns success. /// </summary> private static bool tryResolve( Type targetType, out object result, ServiceConstructorRequest request, IServiceRegistrationProvider serviceProvider, Func <Type, object> instanceProvider, bool logMustResolve) { bool CheckResult(object service, string sourceName, out object successResult) { if (targetType.IsInstanceOfType(service)) { request.TraceStack.Add($"{sourceName} resolved '{targetType.GetFriendlyFullName()}'."); successResult = service; return(true); } successResult = null; return(false); } if (instanceProvider != null) { if (CheckResult(instanceProvider(targetType), "InstanceProvider Func", out result)) { return(true); } } if (CheckResult(serviceProvider.GetService(targetType, request), nameof(IServiceProvider), out result)) { return(true); } if (serviceProvider.ParentServiceProvider is IServiceRegistrationProvider parentServiceRegistrationProvider) { if (CheckResult( parentServiceRegistrationProvider.GetService(targetType, request), nameof(IServiceRegistrationProvider.ParentServiceProvider), out result)) { return(true); } } else { if (CheckResult( serviceProvider.ParentServiceProvider?.GetService(targetType), nameof(IServiceRegistrationProvider.ParentServiceProvider), out result)) { return(true); } } if (logMustResolve) { request.TraceStack.Add($"Did not resolve '{targetType.GetFriendlyFullName()}'."); } return(false); }
/// <summary> /// The implementation method that constructs and/or returns the /// implementation instance. /// </summary> /// <param name="serviceConstructorRequest">This argument is required here.</param> /// <returns>Should be null only if the service is not constructed successfully: /// note that this may result in a resolver or constructor error.</returns> /// <exception cref="ArgumentNullException"></exception> internal object Get(ServiceConstructorRequest serviceConstructorRequest) { if (serviceConstructorRequest == null) { throw new ArgumentNullException(nameof(serviceConstructorRequest)); } lock (syncLock) { checkIsDisposedUnsafe(); if (!IsSingleton) { ConstructedAt = DateTime.UtcNow; object instance = InvokeFactory(serviceConstructorRequest); if (dependencies != null) { dependencies.TryAddRange(serviceConstructorRequest.Dependencies); } else { dependencies = new MultiDictionary <Type, Type>( serviceConstructorRequest.Dependencies, serviceConstructorRequest.Dependencies.Comparer); } return(instance); } if (IsSingletonSet) { return(singleton); } ConstructedAt = DateTime.UtcNow; singleton = InvokeFactory(serviceConstructorRequest); IsSingletonSet = true; dependencies = new MultiDictionary <Type, Type>( serviceConstructorRequest.Dependencies, serviceConstructorRequest.Dependencies.Comparer); return(singleton); } object InvokeFactory(ServiceConstructorRequest request) => factory != null ? factory(serviceProvider) : ServiceConstructorMethods.TryConstruct( ImplementationType, out object result, request, serviceProvider, null, false, RequireConstructorAttributes, ConstructorAttributeTypes) ? result : null; }
private object tryGetService( Type serviceType, ServiceConstructorRequest serviceConstructorRequest) { if (serviceType == null) { throw new ArgumentNullException(nameof(serviceType)); } object service = serviceProvider.GetService(serviceType); return(serviceType.IsInstanceOfType(service) ? service : parentServiceRegistrationProvider != null ? parentServiceRegistrationProvider.GetService( serviceType, serviceConstructorRequest ?? new ServiceConstructorRequest( TraceSources.For <ServiceRegistrationProviderWrapper>())) : ParentServiceProvider?.GetService(serviceType)); }
public static bool TryConstruct( Type targetType, out object service, ServiceConstructorRequest request, IServiceRegistrationProvider serviceProvider, Func <Type, object> instanceProvider = null, bool tryConstructArguments = false, bool?requireConstructorAttributes = null, IReadOnlyCollection <Type> constructorAttributeTypes = null) { if (targetType == null) { throw new ArgumentNullException(nameof(targetType)); } if (request == null) { throw new ArgumentNullException(nameof(request)); } if (serviceProvider == null) { throw new ArgumentNullException(nameof(serviceProvider)); } if ((constructorAttributeTypes == null) || (constructorAttributeTypes.Count == 0)) { constructorAttributeTypes = new[] { typeof(ServiceProviderConstructorAttribute) } } ; if (request.ConstructingTypes.Contains(targetType)) { request.TraceStack.Add( "Found a recursive constructor dependency" + $": '{targetType.GetFriendlyFullName()}'" + " ... cannot continue."); service = null; return(false); } request.ConstructingTypes.Add(targetType); request.Logger.Verbose("Constructing {0}.", targetType.GetFriendlyFullName()); if (ServiceConstructorMethods.invokeMember( ServiceConstructorMethods.findConstructors( targetType, requireConstructorAttributes, constructorAttributeTypes, request.TraceStack), false, null, out service, request, serviceProvider, instanceProvider, tryConstructArguments, requireConstructorAttributes, constructorAttributeTypes, false)) { request.Logger.Verbose( "Construct result for '{0}' is true: '{1}'.", targetType.GetFriendlyFullName(), service.GetType().GetFriendlyFullName()); request.ConstructingTypes.Remove(targetType); return(true); } request.Logger.Warning("Construct result for '{0}' is false.", targetType.GetFriendlyFullName()); request.ConstructingTypes.Remove(targetType); return(false); }
private static bool invokeMember( IEnumerable <MethodBase> members, bool isMethod, object methodTarget, out object newInstance, ServiceConstructorRequest request, IServiceRegistrationProvider serviceProvider, Func <Type, object> instanceProvider, bool tryConstructArguments, bool?requireConstructorAttributes, IReadOnlyCollection <Type> constructorAttributeTypes, bool isRecursed) { newInstance = null; bool success = false; foreach (MethodBase methodBase in members) { ParameterInfo[] parameters = methodBase.GetParameters(); if (parameters.Length == 0) { success = isMethod ? ServiceConstructorMethods.tryInvokeMethod( methodTarget, (MethodInfo)methodBase, new object[0], request.TraceStack) : ServiceConstructorMethods.tryInvokeConstructor( (ConstructorInfo)methodBase, new object[0], out newInstance, request.TraceStack); break; } List <object> arguments = new List <object>(parameters.Length); foreach (ParameterInfo parameterInfo in parameters) { if (ServiceConstructorMethods.tryResolve( parameterInfo.ParameterType, out object parameterResult, request, serviceProvider, instanceProvider, !tryConstructArguments)) { arguments.Add(parameterResult); continue; } if (tryConstructArguments) { if (request.ConstructingTypes.Contains(parameterInfo.ParameterType)) { request.TraceStack.Add( "Found a recursive constructor dependency" + $": '{parameterInfo.ParameterType.GetFriendlyFullName()}'" + " ... cannot continue."); break; } request.ConstructingTypes.Add(parameterInfo.ParameterType); bool argumentSuccess = ServiceConstructorMethods.invokeMember( ServiceConstructorMethods.findConstructors( parameterInfo.ParameterType, requireConstructorAttributes, constructorAttributeTypes, request.TraceStack), false, null, out object argumentResult, request, serviceProvider, instanceProvider, true, requireConstructorAttributes, constructorAttributeTypes, true); request.ConstructingTypes.Remove(parameterInfo.ParameterType); if (argumentSuccess) { arguments.Add(argumentResult); continue; } } if (parameterInfo.HasDefaultValue) { request.TraceStack.Add( $"Parameter '{parameterInfo.ParameterType.GetFriendlyFullName()}' has default value."); arguments.Add(parameterInfo.DefaultValue); } else { break; } } if ((arguments.Count != parameters.Length) || (isMethod ? !ServiceConstructorMethods.tryInvokeMethod( methodTarget, (MethodInfo)methodBase, arguments.ToArray(), request.TraceStack) : !ServiceConstructorMethods.tryInvokeConstructor( (ConstructorInfo)methodBase, arguments.ToArray(), out newInstance, request.TraceStack))) { continue; } request.Dependencies.TryAddRange( methodBase.DeclaringType, parameters.Select(parameter => parameter.ParameterType)); success = true; break; } if (isRecursed) { return(success); } if (success) { if (request.Logger.IsVerbose()) { request.Logger.Verbose(GetTraceMessage()); } } else { if (request.Logger.IsInfo()) { request.Logger.Info(GetTraceMessage()); } } string GetTraceMessage() { string separator = $"{Environment.NewLine} "; StringBuilder sb = request.TraceStack.ToConcatenatedString(null, separator); if (sb.Length != 0) { sb.Insert(0, " "); } return(sb.ToString()); } return(success); }
object IServiceRegistrationProvider.GetService( Type serviceType, ServiceConstructorRequest serviceConstructorRequest) => tryGetService(serviceType, serviceConstructorRequest);