예제 #1
0
 /// <summary>
 ///     Use <see cref="All" /> to find a <c>Type</c> which is assignable to <paramref name="type" />
 /// </summary>
 /// <param name="type"></param>
 /// <param name="typesWaitingToBeBuilt"></param>
 /// <param name="searchAnchor"></param>
 /// <returns>The <c>Type</c> if one is found, <c>null</c> if not.</returns>
 public Type FindTypeAssignableTo(Type type, IEnumerable <Type> typesWaitingToBeBuilt = null, object searchAnchor = null)
 {
     return(TypeFinder.FindConcreteTypeAssignableTo(type, All, typesWaitingToBeBuilt, searchAnchor));
 }
        /// <summary>
        ///     Creates an instance of something assignable to <paramref name="type" /> using <see cref="Rules" />
        ///     and <see cref="SearchAnchor" />
        /// </summary>
        /// <param name="type">The type of which a concrete instance is wanted.</param>
        /// <param name="typesWaitingToBeBuilt">
        ///     The 'stack' of types we are trying to build grows as instantiating a type
        ///     recursively requires the instantion of its constructor dependencies.
        ///     This parameter is for the benefit of recursive rules whose strategy may vary depending on what we're trying
        ///     to build.
        /// </param>
        /// <returns>An instance of type <paramref name="type" /> if possible, <c>default(T)</c> if unable to construct one.</returns>
        object New(Type type, IEnumerable <Type> typesWaitingToBeBuilt)
        {
            if (typesWaitingToBeBuilt?.Count() >= RecursionLimit)
            {
                return(RecursionLimitReturnFunc(type, typesWaitingToBeBuilt, SearchAnchor));
            }

            typesWaitingToBeBuilt = (typesWaitingToBeBuilt ?? new List <Type>()).Union(type);

            var instanceResult   = new ActivateInstances(Instances).CreateInstance(type, typesWaitingToBeBuilt, SearchAnchor);
            var customRuleResult =
                instanceResult
                ?? Rules.OfType <IActivateInstanceRule>()
                .Select(r => r.CreateInstance(type, typesWaitingToBeBuilt, SearchAnchor))
                .FirstOrDefault();

            var ainfo = new ActivationInfo {
                TypeStack = typesWaitingToBeBuilt
            };

            try
            {
                if (customRuleResult != null)
                {
                    LastActivationTree.Add(ainfo = ActivationInfo.InstanceRule(typesWaitingToBeBuilt));
                    return(customRuleResult);
                }
                else if (type.IsAbstract || type.IsInterface)
                {
                    ainfo = new ActivationInfo {
                        How = "type.IsAbstract || type.IsInterface", TypeStack = typesWaitingToBeBuilt
                    };
                    var concreteTypeFound = TypeFinder.FindConcreteTypeAssignableTo(type, Rules, typesWaitingToBeBuilt, SearchAnchor);
                    return(concreteTypeFound == null
                                           ? null
                                           : New(concreteTypeFound, typesWaitingToBeBuilt));
                }
                else if (type == typeof(string))
                {
                    LastActivationTree.Add(ainfo = ActivationInfo.ValueType(typesWaitingToBeBuilt));
                    return("for" + typesWaitingToBeBuilt.Reverse().Skip(1).FirstOrDefault());
                }
                else if (type.IsValueType)
                {
                    LastActivationTree.Add(ainfo = ActivationInfo.ValueType(typesWaitingToBeBuilt));
                    return(Activator.CreateInstance(type));
                }
                else
                {
                    ainfo = new ActivationInfo {
                        How = "InstanceFromConstructorRules", TypeStack = typesWaitingToBeBuilt
                    };
                }

                return(InstanceFromConstructorRules(type, Rules, typesWaitingToBeBuilt, SearchAnchor));
            } catch (Exception e)
            {
                LastErrorList?.Add(new KeyValuePair <ActivationInfo, Exception>(ainfo, e));
                return(null);
            }
        }