/// <summary> /// Use <see cref="Activator.CreateInstance(System.Type)" /> to activate an Instance of the concrete type /// <paramref name="type" />. Use the <see cref="IChooseConstructorRule" /> to choose a constructor. /// If the chosen constructor has dependencies, then recursively use <see cref="New" /> to create them. /// </summary> /// <param name="type">This should be a concrete type, otherwise activation will fail.</param> /// <param name="rules"> /// <see cref="IActivateAnythingRule" /> rules are of three kinds: /// <list type="bullet"> /// <item> /// <see cref="IActivateInstanceRule" /> provides an immediate source of a concrete /// type. For instance, the <see cref="CreateFromFactoryMethod" /> rule. /// </item> /// <item> /// <see cref="IFindTypeRule" /> provides rules for where to look for candidate /// concrete subTypes of <paramref name="type" />. /// </item> /// <item> /// <see cref="IChooseConstructorRule" /> rules for how to choose between constructors when /// the <see cref="IFindTypeRule" />s have found a <c>Type</c> to instantiate. /// </item> /// </list> /// If<paramref name="rules" /> is null, the <see cref="DefaultRules" /> will be used. /// </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> /// <param name="searchAnchor"> /// The <see cref="Type" /> and especially the <see cref="Type.Assembly" /> of /// <c>searchAnchor</c> may be used by some rules as a reference point—whether as a starting point or as a limit—to /// their search. For instance, the <see cref="FindInAnchorAssembly" /> rule will only look for concrete /// types in the anchor Assembly. /// </param> /// <returns>An instance of type <paramref name="type" /> if possible; default(Type) if unable to construct one.</returns> protected object InstanceFromConstructorRules( Type type, IEnumerable <IActivateAnythingRule> rules, IEnumerable <Type> typesWaitingToBeBuilt, object searchAnchor) { var constructor = ChooseConstructor(type, rules.OfType <IChooseConstructorRule>(), typesWaitingToBeBuilt, searchAnchor); if (constructor == null) { var instance = Activator.CreateInstance(type); LastActivationTree.Add(ActivationInfo.NoConstructor(typesWaitingToBeBuilt)); return(instance); } else if (constructor.GetParameters().Length == 0 && constructor.IsPublic) { var instance = Activator.CreateInstance(type); LastActivationTree.Add(ActivationInfo.Constructed(typesWaitingToBeBuilt, constructor)); return(instance); } else if (constructor.GetParameters().Length == 0 && !constructor.IsPublic) { var instance = Activator.CreateInstance(type, true); LastActivationTree.Add(ActivationInfo.Constructed(typesWaitingToBeBuilt, constructor)); return(instance); } else { var bindingFlags = constructor.IsPublic ? BindingFlags.Public : BindingFlags.NonPublic; bindingFlags |= BindingFlags.Instance; var pars = constructor.GetParameters() .Select(p => typesWaitingToBeBuilt.Contains(p.ParameterType) && p.IsOptional ? p.ParameterType.DefaultValue() : New(p.ParameterType, typesWaitingToBeBuilt) ) .ToArray(); var instance = constructor.Invoke(bindingFlags, null, pars, CultureInfo.CurrentCulture); LastActivationTree.Add(ActivationInfo.Constructed(typesWaitingToBeBuilt, constructor, pars)); return(instance); } }
/// <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); } }