/// <summary> /// Return the list of constructor for a type that can be instantiated with the Registry, /// i.e. whose parameters are registered or instantiable. /// </summary> IEnumerable <ConstructorInfo> FindConstructors(Type type, RequestCache cache) { if (FindSession == null) { FindSession = new Stack <Type>(); } if (FindSession.Contains(type)) { yield break; } FindSession.Push(type); try { if (!CanBeInstantiated(type)) { yield break; } var ctors = type.GetTypeInfo().DeclaredConstructors; foreach (var c in ctors) { bool ok = true; foreach (var p in c.GetParameters()) { var impa = p.GetCustomAttribute <ImportAttribute>(); var t = (impa != null ? impa.ImportedType : null) ?? p.ParameterType; var vault = FindRegistrations(t, cache).FirstOrDefault(x => x.Instance != null || x.Type != type); if (vault != null) { continue; } if (p.HasDefaultValue) { continue; } if (CanCreate(p.ParameterType, cache)) { continue; } ok = false; break; } if (ok) { yield return(c); } } } finally { FindSession.Pop(); } }
/// <summary> /// Return the list of constructor for a type that can be instantiated with the Registry, /// i.e. whose parameters are registered or instantiable. /// </summary> public static IEnumerable <ConstructorInfo> FindConstructors(ITypeTree <ServiceDefinition> services, ITypeTree <object> scope, Type type) { if (FindSession == null) { FindSession = new Stack <Type>(); } if (FindSession.Contains(type) || !CanBeInstantiated(type)) { return(Array.Empty <ConstructorInfo>()); } FindSession.Push(type); try { return (from c in type.GetTypeInfo().DeclaredConstructors let parameters = c.GetParameters() where parameters.All(x => CanCreateParameter(x)) let N = parameters.Length let difficulty = parameters.Select(x => IsKnownParameter(x) ? 0 : 1).Sum() orderby difficulty ascending, N descending select c ); bool CanCreateParameter(ParameterInfo pi) { var impa = pi.GetCustomAttribute <ImportAttribute>(); var t = (impa != null ? impa.ImportedType : null) ?? pi.ParameterType; if (t.IsValueType) { return(true); } var descendant = MergeKeys(services, scope, t).Where(x => x != type).FirstOrDefault(); if (descendant != null) { return(true); } if (pi.HasDefaultValue) { return(true); } if (CanCreate(services, scope, pi.ParameterType)) { return(true); } return(false); } bool IsKnownParameter(ParameterInfo pi) { var impa = pi.GetCustomAttribute <ImportAttribute>(); var t = (impa != null ? impa.ImportedType : null) ?? pi.ParameterType; var descendant = MergeKeys(services, scope, t).Where(x => x != type).FirstOrDefault(); if (descendant != null) { return(true); } return(false); } } finally { FindSession.Pop(); } }