private static Type FindType(string typeName, IEnumerable <Assembly> asmSearch, MethodInfo declaringMethod = null)
        {
            typeName = typeName.Trim();
            if (string.IsNullOrEmpty(typeName))
            {
                return(null);
            }

            // Retrieve generic parameters
            Match genericParamsMatch = Regex.Match(typeName, @"(\[)(\[.+\])(\])");

            string[] genericParams = null;
            if (genericParamsMatch.Groups.Count > 3)
            {
                string genericParamList = genericParamsMatch.Groups[2].Value;
                genericParams = SplitArgs(genericParamList, '[', ']', ',', 0);
                for (int i = 0; i < genericParams.Length; i++)
                {
                    genericParams[i] = genericParams[i].Substring(1, genericParams[i].Length - 2);
                }
            }

            // Process type name
            string[] token           = Regex.Split(typeName, @"\[\[.+\]\]");
            string   typeNameBase    = token[0];
            string   elementTypeName = typeName;

            // Handle Reference
            string lastToken = token[token.Length - 1];

            if (lastToken.Length > 0 && lastToken[lastToken.Length - 1] == '&')
            {
                Type elementType = ResolveType(typeName.Substring(0, typeName.Length - 1), asmSearch, declaringMethod);
                if (elementType == null)
                {
                    return(null);
                }
                return(elementType.MakeByRefType());
            }

            // Retrieve array ranks
            int             arrayRank    = 0;
            MatchCollection arrayMatches = Regex.Matches(token[token.Length - 1], @"\[,*\]");

            if (arrayMatches.Count > 0)
            {
                string rankStr    = arrayMatches[arrayMatches.Count - 1].Value;
                int    commaCount = 0;
                for (int i = 0; i < rankStr.Length; i++)
                {
                    if (rankStr[i] == ',')
                    {
                        commaCount++;
                    }
                }
                arrayRank       = 1 + commaCount;
                elementTypeName = elementTypeName.Substring(0, elementTypeName.Length - rankStr.Length);
            }

            // Handle Arrays
            if (arrayRank > 0)
            {
                Type elementType = ResolveType(elementTypeName, asmSearch, declaringMethod);
                if (elementType == null)
                {
                    return(null);
                }
                return(arrayRank == 1 ? elementType.MakeArrayType() : elementType.MakeArrayType(arrayRank));
            }

            Type baseType = null;

            // Generic method parameter Types
            if (typeNameBase.StartsWith("``"))
            {
                if (declaringMethod != null)
                {
                    int    methodGenArgIndex;
                    string genericTypeIndexToken = typeNameBase.Substring(2, typeNameBase.Length - 2);
                    if (int.TryParse(genericTypeIndexToken, out methodGenArgIndex))
                    {
                        Type[] genericMethodArguments = declaringMethod.GetGenericArguments();
                        if (methodGenArgIndex >= 0 && methodGenArgIndex < genericMethodArguments.Length)
                        {
                            baseType = genericMethodArguments[methodGenArgIndex];
                        }
                    }
                }
            }
            else
            {
                // Retrieve base type
                foreach (Assembly assembly in asmSearch)
                {
                    baseType = assembly.GetType(typeNameBase);
                    if (baseType != null)
                    {
                        break;
                    }
                }
                // Failed to retrieve base type? Try manually and ignore plus / dot difference.
                if (baseType == null)
                {
                    string assemblyNameGuess = typeName.Split('.', '+').FirstOrDefault();
                    IEnumerable <Assembly> sortedAsmSearch = asmSearch.OrderByDescending(a => a.GetShortAssemblyName() == assemblyNameGuess);
                    foreach (Assembly assembly in sortedAsmSearch)
                    {
                        // Try to retrieve all Types from the current Assembly
                        TypeInfo[] definedTypes;
                        try { definedTypes = assembly.DefinedTypes.ToArray(); }
                        catch (Exception) { continue; }

                        // Iterate and manually compare names
                        foreach (TypeInfo typeInfo in definedTypes)
                        {
                            if (IsFullTypeNameEqual(typeNameBase, typeInfo.FullName))
                            {
                                baseType = typeInfo.AsType();
                                break;
                            }
                        }
                        if (baseType != null)
                        {
                            break;
                        }
                    }
                }
                // Failed anyway? Try explicit resolve
                if (baseType == null)
                {
                    ResolveMemberEventArgs args = new ResolveMemberEventArgs(typeNameBase);
                    if (TypeResolve != null)
                    {
                        TypeResolve(null, args);
                    }
                    baseType = (args.ResolvedMember is TypeInfo) ? (args.ResolvedMember as TypeInfo).AsType() : null;
                }
            }

            // Retrieve generic type params
            if (genericParams != null)
            {
                Type[] genericParamTypes = new Type[genericParams.Length];

                for (int i = 0; i < genericParamTypes.Length; i++)
                {
                    // Explicitly referring to generic type definition params: Don't attemp to make it generic.
                    if ((genericParams[i].Length > 0 && genericParams[i][0] == '`') &&
                        (genericParams[i].Length < 2 || genericParams[i][1] != '`'))
                    {
                        return(baseType);
                    }

                    genericParamTypes[i] = ResolveType(genericParams[i], asmSearch, declaringMethod);

                    // Can't find the generic type argument: Fail.
                    if (genericParamTypes[i] == null)
                    {
                        return(null);
                    }
                }

                if (baseType == null)
                {
                    return(null);
                }
                else
                {
                    return(baseType.MakeGenericType(genericParamTypes));
                }
            }

            return(baseType);
        }
        private static MemberInfo FindMember(string memberString, IEnumerable <Assembly> asmSearch)
        {
            string[] token = memberString.Split(':');

            char memberTypeToken;
            Type declaringType;

            // If there is no member type token, it is actually a type id.
            if (token.Length == 1)
            {
                Type type = ResolveType(token[0], asmSearch, null);
                declaringType   = type != null ? type : null;
                memberTypeToken = MemberTokenTypeInfo;
            }
            // Otherwise, determine the member type using the member type token
            else if (token.Length > 1)
            {
                Type type = ResolveType(token[1], asmSearch, null);
                declaringType   = type != null ? type : null;
                memberTypeToken = (token[0].Length > 0) ? token[0][0] : MemberTokenUndefined;
            }
            // If we have nothing (empty string, etc.), fail
            else
            {
                declaringType   = null;
                memberTypeToken = MemberTokenUndefined;
            }

            if (declaringType != null && memberTypeToken != ' ')
            {
                TypeInfo declaringTypeInfo = declaringType.GetTypeInfo();

                if (memberTypeToken == MemberTokenTypeInfo)
                {
                    return(declaringType.GetTypeInfo());
                }
                else if (memberTypeToken == MemberTokenFieldInfo)
                {
                    MemberInfo member = declaringType.GetRuntimeFields().FirstOrDefault(m => m.Name == token[2]);
                    if (member != null)
                    {
                        return(member);
                    }
                }
                else if (memberTypeToken == MemberTokenEventInfo)
                {
                    MemberInfo member = declaringType.GetRuntimeEvents().FirstOrDefault(m => m.Name == token[2]);
                    if (member != null)
                    {
                        return(member);
                    }
                }
                else
                {
                    int      memberParamListStartIndex = token[2].IndexOf('(');
                    int      memberParamListEndIndex   = token[2].IndexOf(')');
                    string   memberParamList           = memberParamListStartIndex != -1 ? token[2].Substring(memberParamListStartIndex + 1, memberParamListEndIndex - memberParamListStartIndex - 1) : null;
                    string[] memberParams     = SplitArgs(memberParamList, '[', ']', ',', 0);
                    string   memberName       = memberParamListStartIndex != -1 ? token[2].Substring(0, memberParamListStartIndex) : token[2];
                    Type[]   memberParamTypes = memberParams.Select(p => ResolveType(p, asmSearch, null)).ToArray();

                    if (memberTypeToken == MemberTokenConstructorInfo)
                    {
                        bool lookForStatic           = memberName == "s";
                        ConstructorInfo[] availCtors = declaringTypeInfo.DeclaredConstructors.Where(m =>
                                                                                                    m.IsStatic == lookForStatic &&
                                                                                                    m.GetParameters().Length == memberParams.Length).ToArray();
                        foreach (ConstructorInfo ctor in availCtors)
                        {
                            bool            possibleMatch = true;
                            ParameterInfo[] methodParams  = ctor.GetParameters();
                            for (int i = 0; i < methodParams.Length; i++)
                            {
                                string methodParamTypeName = methodParams[i].ParameterType.Name;
                                if (methodParams[i].ParameterType != memberParamTypes[i] && methodParamTypeName != memberParams[i])
                                {
                                    possibleMatch = false;
                                    break;
                                }
                            }
                            if (possibleMatch)
                            {
                                return(ctor);
                            }
                        }
                    }
                    else if (memberTypeToken == MemberTokenPropertyInfo)
                    {
                        PropertyInfo[] availProps = declaringType.GetRuntimeProperties().Where(m =>
                                                                                               m.Name == memberName &&
                                                                                               m.GetIndexParameters().Length == memberParams.Length).ToArray();
                        foreach (PropertyInfo prop in availProps)
                        {
                            bool            possibleMatch = true;
                            ParameterInfo[] methodParams  = prop.GetIndexParameters();
                            for (int i = 0; i < methodParams.Length; i++)
                            {
                                string methodParamTypeName = methodParams[i].ParameterType.Name;
                                if (methodParams[i].ParameterType != memberParamTypes[i] && methodParamTypeName != memberParams[i])
                                {
                                    possibleMatch = false;
                                    break;
                                }
                            }
                            if (possibleMatch)
                            {
                                return(prop);
                            }
                        }
                    }

                    int    genArgTokenStartIndex = token[2].IndexOf("``", StringComparison.Ordinal);
                    int    genArgTokenEndIndex   = memberParamListStartIndex != -1 ? memberParamListStartIndex : token[2].Length;
                    string genArgToken           = genArgTokenStartIndex != -1 ? token[2].Substring(genArgTokenStartIndex + 2, genArgTokenEndIndex - genArgTokenStartIndex - 2) : "";
                    if (genArgTokenStartIndex != -1)
                    {
                        memberName = token[2].Substring(0, genArgTokenStartIndex);
                    }

                    int      genArgListStartIndex = genArgToken.IndexOf('[');
                    int      genArgListEndIndex   = genArgToken.LastIndexOf(']');
                    string   genArgList           = genArgListStartIndex != -1 ? genArgToken.Substring(genArgListStartIndex + 1, genArgListEndIndex - genArgListStartIndex - 1) : null;
                    string[] genArgs = SplitArgs(genArgList, '[', ']', ',', 0);
                    for (int i = 0; i < genArgs.Length; i++)
                    {
                        genArgs[i] = genArgs[i].Substring(1, genArgs[i].Length - 2);
                    }

                    int genArgCount = genArgToken.Length > 0 ? int.Parse(genArgToken.Substring(0, genArgListStartIndex != -1 ? genArgListStartIndex : genArgToken.Length)) : 0;

                    // Select the method that fits
                    MethodInfo[] availMethods = declaringType.GetRuntimeMethods().Where(m =>
                                                                                        m.Name == memberName &&
                                                                                        m.GetGenericArguments().Length == genArgCount &&
                                                                                        m.GetParameters().Length == memberParams.Length).ToArray();
                    foreach (MethodInfo method in availMethods)
                    {
                        bool            possibleMatch = true;
                        ParameterInfo[] methodParams  = method.GetParameters();
                        for (int i = 0; i < methodParams.Length; i++)
                        {
                            string methodParamTypeName = methodParams[i].ParameterType.Name;
                            if (methodParams[i].ParameterType != memberParamTypes[i] && methodParamTypeName != memberParams[i])
                            {
                                possibleMatch = false;
                                break;
                            }
                        }
                        if (possibleMatch)
                        {
                            return(method);
                        }
                    }
                }
            }

            // Failed? Try explicit resolve
            ResolveMemberEventArgs args = new ResolveMemberEventArgs(memberString);

            if (MemberResolve != null)
            {
                MemberResolve(null, args);
            }
            return(args.ResolvedMember);
        }