/// <summary> /// Determines the sequence of command invocations, property accesses, /// and constructor calls that are required to instantiate an object of /// the requested type, given the current state of the context. /// </summary> /// <returns>A Stack containing the methods/properties/ctors to be invoked /// to create an instance of the desire type. The stack may be empty if an /// object of the desired type is already available. /// </returns> /// <exception>Throws ContextException if an object of the desired type /// cannot be created from the current context. /// </exception> public Stack <Factory> FindPathToType(Type t, Command cmd) { var steps = new Stack <Factory>(); _log.TraceFormat("Determining steps needed to create an instance of {0}", t); // Create a lambda for recursion Action <Type> scan = null; scan = type => { if (!HasObject(type)) { // See if we can get an instance from what we do have if (_registry.Contains(type)) { Factory factory = _registry.GetFactory(type); _log.DebugFormat("Found {0} on {1}", factory, factory.DeclaringType); steps.Push(factory); if (factory.IsConstructor) { // Determine steps needed to obtain instances of // constructor arguments (if any) foreach (var param in factory.Constructor.GetParameters()) { scan(param.ParameterType); } } else { // Determine how to obtain an instance of the item // holding the factory method/property scan(factory.DeclaringType); } } else { throw new ContextException(string.Format("No method, property, or constructor " + "is registered as a Factory for {0} objects, which are required by " + "{1}", type, cmd.Name)); } } }; scan(t); return(steps); }