Ejemplo n.º 1
0
        /// <summary>
        /// Intended for resolving method calls of types defined in another assembly.
        /// </summary>
        /// <param name="owningAsm"></param>
        /// <param name="tokenName">The name as drafted from <see cref="AssemblyAnalysis.ConvertToMetadataTokenName"/></param>
        /// <param name="mi"></param>
        /// <param name="msgOut">Intended for debug trace from the Console.</param>
        /// <returns></returns>
        internal bool TryResolveRtMemberInfo(Assembly owningAsm, string tokenName, out MemberInfo mi, StringBuilder msgOut = null)
        {
            //default the out variable
            mi = null;

            //expect token name to match naming given herein
            if (String.IsNullOrWhiteSpace(tokenName))
            {
                if (msgOut != null)
                {
                    msgOut.Append(", Message:'the token name is null'");
                }
                return(false);
            }
            if (!tokenName.Contains(Constants.TYPE_METHOD_NAME_SPLIT_ON))
            {
                if (msgOut != null)
                {
                    msgOut.AppendFormat(", Message:'[{0}] does not contain {1}'", tokenName,
                                        Constants.TYPE_METHOD_NAME_SPLIT_ON);
                }
            }

            if (owningAsm == null)
            {
                if (msgOut != null)
                {
                    msgOut.Append(", Message:'the owning assembly is null'");
                }
                return(false);
            }

            var assemblyName = owningAsm.GetName().Name;
            var typeName     = MetadataTokenName.CtorTypeNameFromTokenName(tokenName, assemblyName);

            if (String.IsNullOrWhiteSpace(typeName))
            {
                if (msgOut != null)
                {
                    msgOut.Append(", Message:'could not parse type name'");
                }
                return(false);
            }
            Type asmType = null;

            try
            {
                //framework throwing null-ref ex despite null checks
                asmType = owningAsm.NfGetType(typeName, false, _myProgram.LogFile);
            }
            catch
            {
                if (msgOut != null)
                {
                    msgOut.Append(", Message:'Assembly.GetType threw exception'");
                }
                return(false);
            }
            if (asmType == null)
            {
                if (msgOut != null)
                {
                    msgOut.AppendFormat(", Message:'assembly {0} could not resolve {1}'", assemblyName,
                                        typeName);
                }
                return(false);
            }

            var methodName = MetadataTokenName.ParseMethodNameFromTokenName(tokenName);

            if (String.IsNullOrWhiteSpace(methodName))
            {
                if (msgOut != null)
                {
                    msgOut.Append(", Message:'could not parse method name'");
                }
                return(false);
            }

            MethodInfo methodInfo = null;

            //try easiest first
            try
            {
                methodInfo = asmType.NfGetMethod(methodName, NfSettings.DefaultFlags);
            }
            catch (AmbiguousMatchException) { }//is overloaded

            //try it the formal way
            if (methodInfo == null)
            {
                var args     = MetadataTokenName.ParseArgsFromTokenName(tokenName).ToArray();
                var argTypes = args.Length <= 0
                    ? Type.EmptyTypes
                    : args.Select(Type.GetType).Where(x => x != null).ToArray();

                //there must be a one-for-one match of string names to first-class types
                if (args.Length == argTypes.Length)
                {
                    methodInfo = asmType.NfGetMethod(methodName, NfSettings.DefaultFlags, null, argTypes, null,
                                                     false, _myProgram.LogFile);
                }
            }

            //try it the very slow but certain way
            if (methodInfo == null)
            {
                var methodInfos = asmType.NfGetMethods(NfSettings.DefaultFlags, false, _myProgram.LogFile);
                if (methodInfos.Length <= 0)
                {
                    if (msgOut != null)
                    {
                        msgOut.AppendFormat(", Assembly:'{0}'\n", assemblyName);
                        msgOut.AppendFormat(", Type:'{0}'\n", typeName);
                        msgOut.Append(", Message:'does not have any methods'");
                    }
                    return(false);
                }
                foreach (var info in methodInfos)
                {
                    var asTokenName = AssemblyAnalysis.ConvertToMetadataTokenName(info, _myProgram.AsmIndicies, IsIgnore, _myProgram.LogFile);
                    if (asTokenName == null || string.IsNullOrWhiteSpace(asTokenName.Name))
                    {
                        continue;
                    }
                    if (string.Equals(asTokenName.Name, tokenName))
                    {
                        methodInfo = info;
                        break;
                    }
                }
            }

            if (methodInfo == null)
            {
                if (msgOut != null)
                {
                    msgOut.AppendFormat(", Assembly:'{0}'\n", assemblyName);
                    msgOut.AppendFormat(", Type:'{0}'\n", typeName);
                    msgOut.AppendFormat(", Method:'{0}'\n", methodName);
                    msgOut.Append(", Message:'was not found'");
                }
                return(false);
            }

            mi = methodInfo;
            return(true);
        }