/// <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);
}