示例#1
0
 /// <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();
     }
 }
示例#2
0
        /// <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();
            }
        }