private static void _resolveProperties(object instance, ResolvingContextExpandingHelper helperContext, TypeResolverTypeMapping mapping, TypeResolverTypeMappingContext context, Type target, List <TypeResolverOption> options) { }
private static ConstructorSelectorContext _getConstructor( TypeResolverTypeMapping mapping, ResolvingContextExpandingHelper context, Type requestedType, TypeInfo requestedTypeInfo) { var constructors = requestedTypeInfo.DeclaredConstructors .Select(x => new ConstructorSelectorContext { ConstructorInfo = x, Parameters = x.GetParameters() .Select(pInfo => new ConstructorSelectorParameterContext(pInfo)).ToList(), Attributes = x.GetCustomAttributes <TypeResolverAttribute>(true) }) .Where(x => !x.Attributes.Any(a => a is ResolveSkipAttribute)) .OrderByDescending( x => x.Attributes.OfType <ResolveOrderAttribute>().FirstOrDefault()?.ResolveOrder ?? 0); return(constructors .FirstOrDefault(c => c.Parameters.All(x => _canResolveParameter(mapping, context, x)))); }
private static object _createInstance(this TypeResolverTypeMapping mapping, ITypeResolver resolver, Type target, List <TypeResolverOption> options) { var context = mapping.GetContext(target); //if (context == null) //{ // if (mapping.AllowResolveDefaults) // { // var opts = new List<TypeResolverOption>(); // if (args != null) // { // opts.AddRange(args.OfType<ConstantNamedValue>()); // opts.AddRange(args.OfType<ConstantTypedValue>()); // opts.AddRange(args.OfType<ValueProvider>()); // } // var result = _recursiveResolve(new ResolvingContextExpandingHelper(mapping, context, opts), // mapping, resolver, context, target, opts); // // Logger.Write( // $"The requested type for construction is not registered in any mapping, type:{target.FullName}", // category: IoCNamespaceOptions.LoggerCategory); // // return result; // //if (target.GetTypeInfo().DeclaredConstructors.Any(x => x.GetParameters().Length == 0)) // //return TypeResolver.Default.Resolve(target); // // // //return null; // } //} var cacheInstance = context.Instance; if (cacheInstance != null) { //var lifeSpan = context.ResolveLifespan; //if (lifeSpan == -1) return cacheInstance; return(cacheInstance); } object result; switch (context.MappingType) { case MappingType.Singleton: { lock (context) { var lazyInstance = context.LazyInstance; if (lazyInstance != null) { result = lazyInstance.GetValue(); context.Instance = result; } else { result = cacheInstance; } } break; } case MappingType.Factory: { var cacheFactory = context.FactoryCache; try { if (cacheFactory) { Monitor.Enter(context); } var f1 = context.Factory1; var instance = f1 != null ? f1() : context.Factory2(target); if (cacheFactory) { context.Instance = instance; } result = instance; } finally { if (cacheFactory) { Monitor.Exit(context); } } break; } case MappingType.Resolve: { var opts = context.Options.OfType <TypeResolverOption>().ToList(); opts.AddRange(options); var helperContext = new ResolvingContextExpandingHelper(opts); result = _recursiveResolve( helperContext: helperContext, mapping: mapping, resolver: resolver, context: context, target: target, @override: null, options: opts); //#### _resolveProperties moved inside _recursiveResolve. ####################### //_resolveProperties(result, // helperContext, // mapping, // context, // target, // opts); break; } default: throw new ArgumentOutOfRangeException(); } var appliers = context.ApplierCallbacks; if (appliers != null) { foreach (var applier in appliers) { applier?.ApplyBindings( result, resolver, mapping, context, options ); } } var queryContextList = options.OfType <IoCQueryContext>(); foreach (var query in queryContextList) { query.SetContext(context); } var queryContextListInternal = options.OfType <_Internal_IoCQueryContext>(); foreach (var query in queryContextListInternal) { query.SetContext(context); } return(result); }
private static object _recursiveResolve( ResolvingContextExpandingHelper helperContext, TypeResolverTypeMapping mapping, ITypeResolver resolver, TypeResolverTypeMappingContext context, Type target, Type @override, List <TypeResolverOption> options) { var requestedType = @override ?? context.ToType ?? context.FromType; var requestedTypeInfo = requestedType.GetTypeInfo(); if (requestedTypeInfo.IsInterface) { Logger.Default.Log( $"Unable to create an interface, target:{target.FullName}, resolvingType:{requestedType.FullName}"); return(null); } if (requestedTypeInfo.IsAbstract) { Logger.Default.Log( $"Unable to create an abstract class, target:{target.FullName}, resolvingType:{requestedType.FullName}"); return(null); } var constructor = _getConstructor( mapping: mapping, context: helperContext, requestedType: requestedType, requestedTypeInfo: requestedTypeInfo); if (constructor == null) { Logger.Default.Log( $"No suitable constructor found, target:{target.FullName}, resolvingType:{requestedType.FullName}"); return(null); } var parameters = new List <object>(); { foreach (var p in constructor.Parameters) { var pInfo = p.ParameterInfo; var pType = pInfo.ParameterType; if (pType == target) { Logger.Default.Log( $"Circular dependency detected, parameter:{pInfo.Name}({p.Name}) from target:{target.FullName}, resolvingType:{requestedType.FullName}"); return(null); } switch (p.ResolvingHint) { case ValueResolvingSourceHint.CurrentContextMappings: { object objInstance = null; if (helperContext.CurrentContextMapping != null) { var objContext = helperContext.CurrentContextMapping.GetContext(pType); objInstance = objContext.Instance; if (objInstance != null) { parameters.Add(objInstance); } else { objInstance = helperContext.CurrentContextMapping.CreateInstance(resolver, pType, options.Cast <object>().ToArray()); if (objInstance != null) { parameters.Add(objInstance); } } } if (objInstance == null) { Logger.Default.Log( $"Failed to resolve parameter, parameter:{pInfo.Name}({p.Name}) from target:{pType.FullName}, resolvingType:{requestedType.FullName}"); return(null); } break; } case ValueResolvingSourceHint.ValueProvider: var value = p.ValueProvider.ValueProviderFactory( TypeResolverDestinationType.ConstructorParameter, pType, p.Name); //if (value == null) return null; parameters.Add(value); break; case ValueResolvingSourceHint.NamedConstants: parameters.Add(helperContext.NamedValues.First(x => x.ParameterName == p.Name) .ParameterValue); break; case ValueResolvingSourceHint.TypedConstants: parameters.Add( helperContext.TypedValues.First(x => x.ParameterType == pType).ParameterValue); break; case ValueResolvingSourceHint.Mappings: { var resolved = _createInstance(mapping, resolver, pType, options); if (resolved == null) { Logger.Default.Log( $"Failed to resolve parameter, parameter:{pInfo.Name}({p.Name}) from target:{pType.FullName}, resolvingType:{requestedType.FullName}"); return(null); } parameters.Add(resolved); break; } case ValueResolvingSourceHint.DefaultValue: parameters.Add(Activator.CreateInstance(pType)); break; case ValueResolvingSourceHint.ParameterOptionalDefaultValue: parameters.Add(pInfo.DefaultValue); break; case ValueResolvingSourceHint.DefaultConstructor: { var resolved = p.IsDefaultConstructorHint ? TypeResolver.Default.Resolve(pType) : _createInstance(mapping, resolver, pType, options); if (resolved == null) { if (p.UseDefaultValue) { parameters.Add(Activator.CreateInstance(pType)); } else { Logger.Default.Log( $"Failed to resolve parameter using default constructor, parameter:{pInfo.Name}({p.Name}) from target:{pType.FullName}, resolvingType:{requestedType.FullName}" ); return(null); } } else { parameters.Add(resolved); } break; } default: throw new ArgumentOutOfRangeException(); } } } object instance; try { instance = constructor.ConstructorInfo.Invoke(parameters.ToArray()); } catch (Exception ex) { Logger.Default.Log( $"An error has been occured when try to invoke constructor, target:{target.FullName}, resolvingType:{requestedType.FullName}" + Environment.NewLine + $"Original exception:{ex}"); throw; } _resolveProperties(instance, helperContext, mapping, context, target, options); return(instance); }
private static bool _canResolveParameter( TypeResolverTypeMapping mapping, ResolvingContextExpandingHelper context, ConstructorSelectorParameterContext parameterInfo) { var pInfo = parameterInfo.ParameterInfo; var useDefaultValue = parameterInfo.Attributes.Any(x => x is ResolveDefaultValueAttribute); parameterInfo.UseDefaultValue = useDefaultValue; if (context.CurrentContextMapping.TypeExists(pInfo.ParameterType)) { parameterInfo.ResolvingHint = ValueResolvingSourceHint.CurrentContextMappings; return(true); } var vP = context.ValueProviders.FirstOrDefault(x => x.CanProvide( TypeResolverDestinationType.ConstructorParameter, pInfo.ParameterType, parameterInfo.Name)); if (vP != null) { parameterInfo.ValueProvider = vP; parameterInfo.ResolvingHint = ValueResolvingSourceHint.ValueProvider; return(true); } if (context.NamedValues.Any(x => x.ParameterName == parameterInfo.Name)) { parameterInfo.ResolvingHint = ValueResolvingSourceHint.NamedConstants; return(true); } if (context.TypedValues.Any(x => x.ParameterType == pInfo.ParameterType)) { parameterInfo.ResolvingHint = ValueResolvingSourceHint.TypedConstants; return(true); } if (mapping.TypeExists(pInfo.ParameterType)) { parameterInfo.ResolvingHint = ValueResolvingSourceHint.Mappings; return(true); } if (pInfo.HasDefaultValue) { parameterInfo.ResolvingHint = ValueResolvingSourceHint.ParameterOptionalDefaultValue; return(true); } if (mapping.AllowResolveDefaults) { var pType = pInfo.ParameterType; var pTypeInfo = pType.GetTypeInfo(); var pConstructors = pTypeInfo.DeclaredConstructors.ToList(); if (pConstructors.Count == 0) { parameterInfo.ResolvingHint = ValueResolvingSourceHint.DefaultValue; return(useDefaultValue); } else if (pConstructors.Any(x => x.GetParameters().Length == 0)) { parameterInfo.ResolvingHint = ValueResolvingSourceHint.DefaultConstructor; parameterInfo.IsDefaultConstructorHint = true; return(true); } else { var result = pConstructors .Any(c => c.GetParameters().All(x => _canResolveParameter( mapping: mapping, context: context, parameterInfo: new ConstructorSelectorParameterContext(x)))); if (result) { parameterInfo.ResolvingHint = ValueResolvingSourceHint.DefaultConstructor; parameterInfo.IsDefaultConstructorHint = false; } return(result); } } return(false); }