private static object GetInstanceOfStep(string step, object instance)
        {
            Type type = instance.GetType();

            if (step.StartsWith("[", StringComparison.InvariantCulture) && step.EndsWith("]", StringComparison.InvariantCulture))
            {
                int    index;
                string indexStr = step.Substring(1, step.Length - 2);

                if (!int.TryParse(indexStr, out index))
                {
                    throw new ArgumentException("Couldn't parse an index from the path step '" + step + "'.");
                }

                // We need to check the current type to see if we can treat it as a list

                if (type.IsArray)
                {
                    Array array = (Array)instance;

                    if (index < 0 || index >= array.Length)
                    {
                        return(null);
                    }

                    return(array.GetValue(index));
                }
                else if (typeof(IList).IsAssignableFrom(type))
                {
                    IList list = (IList)instance;

                    if (index < 0 || index >= list.Count)
                    {
                        return(null);
                    }

                    return(list[index]);
                }
                else if (type.ImplementsOpenGenericInterface(typeof(IList <>)))
                {
                    Type       elementType   = type.GetArgumentsOfInheritedOpenGenericInterface(typeof(IList <>))[0];
                    Type       listType      = typeof(IList <>).MakeGenericType(elementType);
                    MethodInfo getItemMethod = listType.GetMethod("get_Item", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);

                    try
                    {
                        return(getItemMethod.Invoke(instance, new object[] { index }));
                    }
                    catch (Exception)
                    {
                        return(null);
                    }
                }
            }
            else if (step.StartsWith("{", StringComparison.InvariantCultureIgnoreCase) && step.EndsWith("}", StringComparison.InvariantCultureIgnoreCase))
            {
                if (type.ImplementsOpenGenericInterface(typeof(IDictionary <,>)))
                {
                    var dictArgs = type.GetArgumentsOfInheritedOpenGenericInterface(typeof(IDictionary <,>));

                    object key = DictionaryKeyUtility.GetDictionaryKeyValue(step, dictArgs[0]);

                    Type       dictType      = typeof(IDictionary <,>).MakeGenericType(dictArgs);
                    MethodInfo getItemMethod = dictType.GetMethod("get_Item", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);

                    try
                    {
                        return(getItemMethod.Invoke(instance, new object[] { key }));
                    }
                    catch (Exception)
                    {
                        return(null);
                    }
                }
            }
            else
            {
                string privateTypeName = null;
                int    plusIndex       = step.IndexOf('+');

                if (plusIndex >= 0)
                {
                    privateTypeName = step.Substring(0, plusIndex);
                    step            = step.Substring(plusIndex + 1);
                }

                var possibleMembers = type.GetAllMembers(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).Where(n => n is FieldInfo || n is PropertyInfo);

                foreach (var member in possibleMembers)
                {
                    if (member.Name == step)
                    {
                        if (privateTypeName != null && member.DeclaringType.Name != privateTypeName)
                        {
                            continue;
                        }

                        return(member.GetMemberValue(instance));
                    }
                }
            }

            return(null);
        }