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