Example #1
0
        protected void Assemble()
        {
            foreach (var xItem in mItems)
            {
                if (xItem is MethodBase)
                {
                    var        xMethod        = (MethodBase)xItem;
                    var        xParams        = xMethod.GetParameters();
                    var        xParamTypes    = xParams.Select(q => q.ParameterType).ToArray();
                    var        xPlug          = mPlugManager.ResolvePlug(xMethod, xParamTypes);
                    var        xMethodType    = MethodInfo.TypeEnum.Normal;
                    Type       xPlugAssembler = null;
                    MethodInfo xPlugInfo      = null;
                    var        xMethodInline  = xMethod.GetCustomAttribute <InlineAttribute>();
                    if (xMethodInline != null)
                    {
                        // inline assembler, shouldn't come here..
                        continue;
                    }
                    var xMethodIdMethod = mItemsList.IndexOf(xMethod);
                    if (xMethodIdMethod == -1)
                    {
                        throw new Exception("Method not in scanner list!");
                    }
                    if (xPlug != null)
                    {
                        xMethodType = MethodInfo.TypeEnum.NeedsPlug;
                        var xAttrib       = xPlug.GetCustomAttribute <PlugMethodAttribute>();
                        var xInline       = xPlug.GetCustomAttribute <InlineAttribute>();
                        var xMethodIdPlug = mItemsList.IndexOf(xPlug);
                        if (xMethodIdPlug == -1 && xInline == null)
                        {
                            throw new Exception("Plug method not in scanner list!");
                        }
                        if (xAttrib != null && xInline == null)
                        {
                            xPlugAssembler = xAttrib.Assembler;
                            xPlugInfo      = new MethodInfo(xPlug, (uint)xMethodIdPlug, MethodInfo.TypeEnum.Plug, null, xPlugAssembler);

                            var xMethodInfo = new MethodInfo(xMethod, (uint)xMethodIdMethod, xMethodType, xPlugInfo /*, xPlugAssembler*/);
                            if (xAttrib != null && xAttrib.IsWildcard)
                            {
                                xPlugInfo.PluggedMethod = xMethodInfo;
                                var xInstructions = mReader.ProcessMethod(xPlug);
                                if (xInstructions != null)
                                {
                                    ProcessInstructions(xInstructions);
                                    mAsmblr.ProcessMethod(xPlugInfo, xInstructions);
                                }
                            }
                            mAsmblr.GenerateMethodForward(xMethodInfo, xPlugInfo);
                        }
                        else
                        {
                            if (xInline != null)
                            {
                                var xMethodID = mItemsList.IndexOf(xItem);
                                if (xMethodID == -1)
                                {
                                    throw new Exception("Method not in list!");
                                }
                                xPlugInfo = new MethodInfo(xPlug, (uint)xMethodID, MethodInfo.TypeEnum.Plug, null, true);

                                var xMethodInfo = new MethodInfo(xMethod, (uint)xMethodIdMethod, xMethodType, xPlugInfo /*, xPlugAssembler*/);

                                xPlugInfo.PluggedMethod = xMethodInfo;
                                var xInstructions = mReader.ProcessMethod(xPlug);
                                if (xInstructions != null)
                                {
                                    ProcessInstructions(xInstructions);
                                    mAsmblr.ProcessMethod(xPlugInfo, xInstructions);
                                }
                                mAsmblr.GenerateMethodForward(xMethodInfo, xPlugInfo);
                            }
                            else
                            {
                                xPlugInfo = new MethodInfo(xPlug, (uint)xMethodIdPlug, MethodInfo.TypeEnum.Plug, null, xPlugAssembler);

                                var xMethodInfo = new MethodInfo(xMethod, (uint)xMethodIdMethod, xMethodType, xPlugInfo /*, xPlugAssembler*/);
                                mAsmblr.GenerateMethodForward(xMethodInfo, xPlugInfo);
                            }
                        }
                    }
                    else
                    {
                        PlugMethodAttribute xAttrib = null;
                        foreach (PlugMethodAttribute attrib in xMethod.GetCustomAttributes(typeof(PlugMethodAttribute), true))
                        {
                            xAttrib = attrib;
                        }
                        if (xAttrib != null)
                        {
                            if (xAttrib.IsWildcard)
                            {
                                continue;
                            }
                            else if (xAttrib.PlugRequired)
                            {
                                throw new Exception(string.Format("Method {0} requires a plug, but none is implemented", xMethod.Name));
                            }
                            xPlugAssembler = xAttrib.Assembler;
                        }

                        var xMethodInfo   = new MethodInfo(xMethod, (uint)xMethodIdMethod, xMethodType, xPlugInfo, xPlugAssembler);
                        var xInstructions = mReader.ProcessMethod(xMethod);
                        if (xInstructions != null)
                        {
                            ProcessInstructions(xInstructions);
                            mAsmblr.ProcessMethod(xMethodInfo, xInstructions);
                        }
                    }
                }
                else if (xItem is FieldInfo)
                {
                    mAsmblr.ProcessField((FieldInfo)xItem);
                }
            }

            var xTypes   = new HashSet <Type>();
            var xMethods = new HashSet <MethodBase>();

            foreach (var xItem in mItems)
            {
                if (xItem is MethodBase)
                {
                    xMethods.Add((MethodBase)xItem);
                }
                else if (xItem is Type)
                {
                    xTypes.Add((Type)xItem);
                }
            }
            mAsmblr.GenerateVMTCode(xTypes, xMethods, GetTypeUID, x => GetMethodUID(x, false));
        }
Example #2
0
        private MethodBase ResolvePlug(Type aTargetType, List <Type> aImpls, MethodBase aMethod, Type[] aParamTypes)
        {
            //TODO: This method is "reversed" from old - remember that when porting
            MethodBase xResult = null;

            // Setup param types for search
            Type[] xParamTypes;
            if (aMethod.IsStatic)
            {
                xParamTypes = aParamTypes;
            }
            else
            {
                // If its an instance method, we have to add this to the ParamTypes to search
                xParamTypes = new Type[aParamTypes.Length + 1];
                if (aParamTypes.Length > 0)
                {
                    aParamTypes.CopyTo(xParamTypes, 1);
                }
                xParamTypes[0] = aTargetType;
            }

            PlugMethodAttribute xAttrib = null;

            foreach (var xImpl in aImpls)
            {
                // TODO: cleanup this loop, next statement shouldnt be neccessary
                if (xResult != null)
                {
                    break;
                }
                // Plugs methods must be static, and public
                // Search for non signature matches first since signature searches are slower
                xResult = xImpl.GetMethod(aMethod.Name, BindingFlags.Static | BindingFlags.Public
                                          , null, xParamTypes, null);
                if (xResult == null && aMethod.Name == ".ctor")
                {
                    xResult = xImpl.GetMethod("Ctor", BindingFlags.Static | BindingFlags.Public
                                              , null, xParamTypes, null);
                }
                if (xResult == null && aMethod.Name == ".cctor")
                {
                    xResult = xImpl.GetMethod("CCtor", BindingFlags.Static | BindingFlags.Public
                                              , null, xParamTypes, null);
                }

                if (xResult == null)
                {
                    // Search by signature
                    foreach (var xSigMethod in xImpl.GetMethods(BindingFlags.Static | BindingFlags.Public))
                    {
                        // TODO: Only allow one, but this code for now takes the last one
                        // if there is more than one
                        xAttrib = null;
                        foreach (PlugMethodAttribute x in xSigMethod.GetCustomAttributes(typeof(PlugMethodAttribute), false))
                        {
                            xAttrib = x;
                        }

                        if (xAttrib != null && (xAttrib.IsWildcard && !xAttrib.WildcardMatchParameters))
                        {
                            MethodBase xTargetMethod = null;
                            if (String.Compare(xSigMethod.Name, "Ctor", true) == 0 ||
                                String.Compare(xSigMethod.Name, "Cctor", true) == 0)
                            {
                                xTargetMethod = aTargetType.GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance).SingleOrDefault();
                            }
                            else
                            {
                                xTargetMethod = (from item in aTargetType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance)
                                                 where item.Name == xSigMethod.Name
                                                 select item).SingleOrDefault();
                            }
                            if (xTargetMethod == aMethod)
                            {
                                xResult = xSigMethod;
                            }
                        }
                        else
                        {
                            var xParams = xSigMethod.GetParameters();
                            //TODO: Static method plugs dont seem to be separated
                            // from instance ones, so the only way seems to be to try
                            // to match instance first, and if no match try static.
                            // I really don't like this and feel we need to find
                            // an explicit way to determine or mark the method
                            // implementations.
                            //
                            // Plug implementations take "this" as first argument
                            // so when matching we don't include it in the search
                            Type[] xTypesInst        = null;
                            var    xActualParamCount = xParams.Length;
                            foreach (var xParam in xParams)
                            {
                                if (xParam.GetCustomAttributes(typeof(FieldAccessAttribute), false).Length > 0)
                                {
                                    xActualParamCount--;
                                }
                            }
                            Type[] xTypesStatic = new Type[xActualParamCount];
                            // If 0 params, has to be a static plug so we skip
                            // any copying and leave xTypesInst = null
                            // If 1 params, xTypesInst must be converted to Type[0]
                            if (xActualParamCount == 1)
                            {
                                xTypesInst = new Type[0];

                                var xReplaceType = xParams[0].GetCustomAttributes(typeof(FieldTypeAttribute), false);
                                if (xReplaceType.Length == 1)
                                {
                                    xTypesStatic[0] = Type.GetType(((FieldTypeAttribute)xReplaceType[0]).Name, true);
                                }
                                else
                                {
                                    xTypesStatic[0] = xParams[0].ParameterType;
                                }
                            }
                            else if (xActualParamCount > 1)
                            {
                                xTypesInst = new Type[xActualParamCount - 1];
                                var xCurIdx = 0;
                                foreach (var xParam in xParams.Skip(1))
                                {
                                    if (xParam.GetCustomAttributes(typeof(FieldAccessAttribute), false).Length > 0)
                                    {
                                        continue;
                                    }

                                    var xReplaceType = xParam.GetCustomAttributes(typeof(FieldTypeAttribute), false);
                                    if (xReplaceType.Length == 1)
                                    {
                                        xTypesInst[xCurIdx] = Type.GetType(((FieldTypeAttribute)xReplaceType[0]).Name, true);
                                    }
                                    else
                                    {
                                        xTypesInst[xCurIdx] = xParam.ParameterType;
                                    }

                                    xCurIdx++;
                                }
                                xCurIdx = 0;
                                foreach (var xParam in xParams)
                                {
                                    if (xParam.GetCustomAttributes(typeof(FieldAccessAttribute), false).Length > 0)
                                    {
                                        xCurIdx++;
                                        continue;
                                    }
                                    if (xCurIdx >= xTypesStatic.Length)
                                    {
                                        break;
                                    }
                                    xTypesStatic[xCurIdx] = xParam.ParameterType;
                                    xCurIdx++;
                                }
                            }
                            SysReflection.MethodBase xTargetMethod = null;
                            // TODO: In future make rule that all ctor plugs are called
                            // ctor by name, or use a new attrib
                            //TODO: Document all the plug stuff in a document on website
                            //TODO: To make inclusion of plugs easy, we can make a plugs master
                            // that references the other default plugs so user exes only
                            // need to reference that one.
                            // TODO: Skip FieldAccessAttribute if in impl
                            if (xTypesInst != null)
                            {
                                if (string.Compare(xSigMethod.Name, "ctor", true) == 0)
                                {
                                    xTargetMethod = aTargetType.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, CallingConventions.Any, xTypesInst, null);
                                }
                                else
                                {
                                    xTargetMethod = aTargetType.GetMethod(xSigMethod.Name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, CallingConventions.Any, xTypesInst, null);
                                }
                            }
                            // Not an instance method, try static
                            if (xTargetMethod == null)
                            {
                                if (string.Compare(xSigMethod.Name, "cctor", true) == 0 ||
                                    string.Compare(xSigMethod.Name, "ctor", true) == 0)
                                {
                                    xTargetMethod = aTargetType.GetConstructor(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, CallingConventions.Any, xTypesStatic, null);
                                }
                                else
                                {
                                    xTargetMethod = aTargetType.GetMethod(xSigMethod.Name, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, CallingConventions.Any, xTypesStatic, null);
                                }
                            }
                            if (xTargetMethod == aMethod)
                            {
                                xResult = xSigMethod;
                                break;
                            }
                            //if (aMethod.DeclaringType.IsGenericTypeDefinition)
                            //{
                            //    if (xTargetMethod.GetF)
                            //}
                            if (xAttrib != null && xAttrib.Signature != null)
                            {
                                var xName = DataMember.FilterStringForIncorrectChars(LabelName.GenerateFullName(aMethod));
                                if (string.Compare(xName, xAttrib.Signature, true) == 0)
                                {
                                    xResult = xSigMethod;
                                    break;
                                }
                            }
                            xAttrib = null;
                        }
                    }
                }
                else
                {
                    // check if signatur is equal
                    var xResPara     = xResult.GetParameters();
                    var xAMethodPara = aMethod.GetParameters();
                    if (aMethod.IsStatic)
                    {
                        if (xResPara.Length != xAMethodPara.Length)
                        {
                            return(null);
                        }
                    }
                    else
                    {
                        if (xResPara.Length - 1 != xAMethodPara.Length)
                        {
                            return(null);
                        }
                    }
                    for (int i = 0; i < xAMethodPara.Length; i++)
                    {
                        int correctIndex = aMethod.IsStatic ? i : i + 1;
                        if (xResPara[correctIndex].ParameterType != xAMethodPara[i].ParameterType)
                        {
                            return(null);
                        }
                    }
                    if (xResult.Name == "Ctor" && aMethod.Name == ".ctor")
                    {
                    }
                    else if (xResult.Name == "CCtor" && aMethod.Name == ".cctor")
                    {
                    }
                    else if (xResult.Name != aMethod.Name)
                    {
                        return(null);
                    }
                }
            }
            if (xResult == null)
            {
                return(null);
            }

            // If we found a matching method, check for attributes
            // that might disable it.
            //TODO: For signature ones, we could cache the attrib. Thats
            // why we check for null here
            if (xAttrib == null)
            {
                // TODO: Only allow one, but this code for now takes the last one
                // if there is more than one
                foreach (PlugMethodAttribute x in xResult.GetCustomAttributes(typeof(PlugMethodAttribute), false))
                {
                    xAttrib = x;
                }
            }

            // See if we need to disable this plug
            if (xAttrib != null)
            {
                if (!xAttrib.Enabled)
                {
                    //xResult = null;
                    return(null);
                }
                else if (xAttrib.IsMonoOnly)
                {
                    //TODO: Check this against build options
                    //TODO: Two exclusive IsOnly's dont make sense
                    // refactor these as a positive rather than negative
                    // Same thing at type plug level
                    //xResult = null;
                    return(null);
                }
                //else if (xAttrib.Signature != null) {
                //  var xName = DataMember.FilterStringForIncorrectChars(MethodInfoLabelGenerator.GenerateFullName(xResult));
                //  if (string.Compare(xName, xAttrib.Signature, true) != 0) {
                //    xResult = null;
                //  }
                //}
            }

            //if (xAttrib != null && xAttrib.Signature != null)
            //{
            //    var xTargetMethods = aTargetType.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
            //    //System_Void__Indy_IL2CPU_Assembler_Assembler__cctor__
            //    //If signature exists, the search is slow. Signatures
            //    //are infrequent though, so for now we just go slow method
            //    //and have not optimized or cached this info. When we
            //    //redo the plugs, we can fix this.
            //    bool xEnabled=true;
            //    foreach (var xTargetMethod in xTargetMethods)
            //    {
            //        string sName = DataMember.FilterStringForIncorrectChars(MethodInfoLabelGenerator.GenerateFullName(xTargetMethod));
            //        if (string.Compare(sName, xAttrib.Signature, true) == 0)
            //        {
            //            //uint xUID = QueueMethod(xPlugImpl.Plug, "Plug", xMethod, true);
            //            //mMethodPlugs.Add(xTargetMethod, new PlugInfo(xUID, xAttrib.Assembler));
            //            // Mark as disabled, because we already handled it
            //            xEnabled = false;
            //            break;
            //        }
            //    }
            //    // if still enabled, we didn't find our method
            //    if (xEnabled)
            //    {
            //        // todo: more precise error: imagine having a 100K line project, and this error happens...
            //        throw new Exception("Plug target method not found.");
            //    }
            //}
            return(xResult);
        }
Example #3
0
        protected void Assemble()
        {
            foreach (var xItem in mItems)
            {
                if (xItem is MethodBase)
                {
                    var        xMethod        = (MethodBase)xItem;
                    var        xParams        = xMethod.GetParameters();
                    var        xParamTypes    = xParams.Select(q => q.ParameterType).ToArray();
                    var        xPlug          = mPlugManager.ResolvePlug(xMethod, xParamTypes);
                    var        xMethodType    = MethodInfo.TypeEnum.Normal;
                    Type       xPlugAssembler = null;
                    MethodInfo xPlugInfo      = null;
                    if (xPlug != null)
                    {
                        xMethodType = MethodInfo.TypeEnum.NeedsPlug;
                        PlugMethodAttribute xAttrib = null;
                        foreach (PlugMethodAttribute attrib in xPlug.GetCustomAttributes(typeof(PlugMethodAttribute), true))
                        {
                            xAttrib = attrib;
                        }
                        if (xAttrib != null)
                        {
                            xPlugAssembler = xAttrib.Assembler;
                            xPlugInfo      = new MethodInfo(xPlug, (uint)mItemsList.IndexOf(xPlug), MethodInfo.TypeEnum.Plug, null, xPlugAssembler);

                            var xMethodInfo = new MethodInfo(xMethod, (uint)mItemsList.IndexOf(xMethod), xMethodType, xPlugInfo /*, xPlugAssembler*/);
                            if (xAttrib != null && xAttrib.IsWildcard)
                            {
                                xPlugInfo.PluggedMethod = xMethodInfo;
                                var xInstructions = mReader.ProcessMethod(xPlug);
                                if (xInstructions != null)
                                {
                                    ProcessInstructions(xInstructions);
                                    mAsmblr.ProcessMethod(xPlugInfo, xInstructions);
                                }
                            }
                            mAsmblr.GenerateMethodForward(xMethodInfo, xPlugInfo);
                        }
                        else
                        {
                            InlineAttribute inl = null;
                            foreach (InlineAttribute inli in xPlug.GetCustomAttributes(typeof(InlineAttribute), false))
                            {
                                inl = inli;
                            }
                            if (inl != null)
                            {
                                xPlugInfo = new MethodInfo(xPlug, (uint)mItemsList.IndexOf(xItem), MethodInfo.TypeEnum.Plug, null, true);

                                var xMethodInfo = new MethodInfo(xMethod, (uint)mItemsList.IndexOf(xMethod), xMethodType, xPlugInfo /*, xPlugAssembler*/);

                                xPlugInfo.PluggedMethod = xMethodInfo;
                                var xInstructions = mReader.ProcessMethod(xPlug);
                                if (xInstructions != null)
                                {
                                    ProcessInstructions(xInstructions);
                                    mAsmblr.ProcessMethod(xPlugInfo, xInstructions);
                                }
                                mAsmblr.GenerateMethodForward(xMethodInfo, xPlugInfo);
                            }
                            else
                            {
                                xPlugInfo = new MethodInfo(xPlug, (uint)mItemsList.IndexOf(xPlug), MethodInfo.TypeEnum.Plug, null, xPlugAssembler);

                                var xMethodInfo = new MethodInfo(xMethod, (uint)mItemsList.IndexOf(xMethod), xMethodType, xPlugInfo /*, xPlugAssembler*/);
                                if (xAttrib != null && xAttrib.IsWildcard)
                                {
                                    xPlugInfo.PluggedMethod = xMethodInfo;
                                    var xInstructions = mReader.ProcessMethod(xPlug);
                                    if (xInstructions != null)
                                    {
                                        ProcessInstructions(xInstructions);
                                        mAsmblr.ProcessMethod(xPlugInfo, xInstructions);
                                    }
                                }
                                mAsmblr.GenerateMethodForward(xMethodInfo, xPlugInfo);
                            }
                        }
                    }
                    else
                    {
                        PlugMethodAttribute xAttrib = null;
                        foreach (PlugMethodAttribute attrib in xMethod.GetCustomAttributes(typeof(PlugMethodAttribute), true))
                        {
                            xAttrib = attrib;
                        }
                        if (xAttrib != null)
                        {
                            if (xAttrib.IsWildcard)
                            {
                                continue;
                            }
                            xPlugAssembler = xAttrib.Assembler;
                        }

                        var xMethodInfo   = new MethodInfo(xMethod, (uint)mItemsList.IndexOf(xMethod), xMethodType, xPlugInfo, xPlugAssembler);
                        var xInstructions = mReader.ProcessMethod(xMethod);
                        if (xInstructions != null)
                        {
                            ProcessInstructions(xInstructions);
                            mAsmblr.ProcessMethod(xMethodInfo, xInstructions);
                        }
                    }
                }
                else if (xItem is FieldInfo)
                {
                    mAsmblr.ProcessField((FieldInfo)xItem);
                }
            }

            var xTypes   = new HashSet <Type>();
            var xMethods = new HashSet <MethodBase>();

            foreach (var xItem in mItems)
            {
                if (xItem is MethodBase)
                {
                    xMethods.Add((MethodBase)xItem);
                }
                else if (xItem is Type)
                {
                    xTypes.Add((Type)xItem);
                }
            }
            mAsmblr.GenerateVMTCode(xTypes, xMethods, GetTypeUID, x => GetMethodUID(x, false));
        }
Example #4
0
        public void ScanPlugs(Dictionary <Type, List <Type> > aPlugs)
        {
            foreach (var xPlug in aPlugs)
            {
                var xImpls = xPlug.Value;
                foreach (var xImpl in xImpls)
                {
                    #region PlugMethods scan

                    foreach (var xMethod in xImpl.GetMethods(BindingFlags.Public | BindingFlags.Static))
                    {
                        PlugMethodAttribute xAttrib = null;
                        foreach (PlugMethodAttribute x in xMethod.GetCustomAttributes(typeof(PlugMethodAttribute), false))
                        {
                            xAttrib = x;
                        }
                        if (xAttrib == null)
                        {
                            //At this point we need to check the plug method actually
                            //matches a method that might need plugging.
                            // x08 bug
                            // We must check for a number of cases:
                            //   - Public, static and private/internal methods that need plugging
                            //   - Ctor or Cctor

                            bool OK = false;
                            if (xMethod.Name.ToLower() == "ctor" ||
                                xMethod.Name.ToLower() == "cctor")
                            {
                                OK = true;
                            }
                            else
                            {
                                // Skip checking methods related to fields because it's just too messy...
                                // We also skip methods which do method access.
                                if (xMethod.GetParameters().Where(x =>
                                {
                                    return(x.GetCustomAttributes(typeof(FieldAccessAttribute)).Count() > 0 ||
                                           x.GetCustomAttributes(typeof(ObjectPointerAccessAttribute)).Count() > 0);
                                }).Count() > 0)
                                {
                                    OK = true;
                                }
                                else
                                {
                                    var xParamTypes = xMethod.GetParameters().Select(delegate(ParameterInfo x)
                                    {
                                        var result = x.ParameterType;
                                        if (result.IsByRef)
                                        {
                                            result = result.GetElementType();
                                        }
                                        else if (result.IsPointer)
                                        {
                                            result = null;
                                        }
                                        return(result);
                                    }).ToArray();

                                    var posMethods = xPlug.Key.GetMethods(BindingFlags.Instance | BindingFlags.Static |
                                                                          BindingFlags.NonPublic | BindingFlags.Public)
                                                     .Where(x => x.Name == xMethod.Name);
                                    foreach (SysReflection.MethodInfo posInf in posMethods)
                                    {
                                        // If static, no this param
                                        // Otherwise, take into account first param is this param
                                        //This param is either of declaring type, or ref to declaring type or pointer
                                        var posMethParamTypes = posInf.GetParameters().Select(delegate(ParameterInfo x)
                                        {
                                            var result = x.ParameterType;
                                            if (result.IsByRef)
                                            {
                                                result = result.GetElementType();
                                            }
                                            else if (result.IsPointer)
                                            {
                                                result = null;
                                            }
                                            return(result);
                                        }).ToArray();

                                        if (posInf.IsStatic)
                                        {
                                            if (posMethParamTypes.Length != xParamTypes.Length)
                                            {
                                                continue;
                                            }

                                            OK = true;
                                            // Exact params match excl. pointers - there could be "null" types for statics since some could be pointers
                                            for (int i = 0; i < posMethParamTypes.Length; i++)
                                            {
                                                if ((posMethParamTypes[i] == null && xParamTypes[i] == null) || !posMethParamTypes[i].Equals(xParamTypes[i]))
                                                {
                                                    OK = false;
                                                    break;
                                                }
                                            }

                                            if (!OK)
                                            {
                                                continue;
                                            }
                                            else
                                            {
                                                break;
                                            }
                                        }
                                        else
                                        {
                                            // Exact match except possibly 1st param
                                            if (posMethParamTypes.Length != xParamTypes.Length &&
                                                posMethParamTypes.Length != xParamTypes.Length - 1)
                                            {
                                                continue;
                                            }
                                            int offset = 0;

                                            OK = true;
                                            // Exact match except if first param doesn't match, we skip 1st param and restart matching
                                            for (int i = 0; i < posMethParamTypes.Length && (i + offset) < xParamTypes.Length; i++)
                                            {
                                                //Continue if current type is null i.e. was a pointer as that could be any type originally.
                                                if (xParamTypes[i + offset] != null && !posMethParamTypes[i].Equals(xParamTypes[i + offset]))
                                                {
                                                    if (offset == 0)
                                                    {
                                                        offset = 1;
                                                        i      = -1;
                                                    }
                                                    else
                                                    {
                                                        OK = false;
                                                        break;
                                                    }
                                                }
                                            }
                                            if (posMethParamTypes.Length == 0 && xParamTypes.Length > 0)
                                            {
                                                //We use IsAssignableFrom here because _some_ plugs decide to use more generic types for the
                                                //this parameter
                                                OK = xParamTypes[0] == null || xParamTypes[0].IsAssignableFrom(posInf.DeclaringType);
                                            }

                                            if (!OK)
                                            {
                                                continue;
                                            }
                                            else
                                            {
                                                break;
                                            }
                                        }
                                    }
                                }
                            }

                            if (!OK)
                            {
                                if (xAttrib == null ||
                                    xAttrib.IsOptional)
                                {
                                    if (LogWarning != null)
                                    {
                                        LogWarning("Invalid plug method! Target method not found. : " + xMethod.GetFullName());
                                    }
                                }
                            }
                        }
                        else
                        {
                            if (xAttrib.IsWildcard &&
                                xAttrib.Assembler == null)
                            {
                                if (LogWarning != null)
                                {
                                    LogWarning("Wildcard PlugMethods need to use an assembler for now.");
                                }
                            }
                        }
                    }
                    #endregion
                    #region PlugFields scan
                    foreach (var xField in xImpl.GetCustomAttributes(typeof(PlugFieldAttribute), true).Cast <PlugFieldAttribute>())
                    {
                        IDictionary <string, PlugFieldAttribute> xFields = null;
                        if (!mPlugFields.TryGetValue(xPlug.Key, out xFields))
                        {
                            xFields = new Dictionary <string, PlugFieldAttribute>();
                            mPlugFields.Add(xPlug.Key, xFields);
                        }
                        if (xFields.ContainsKey(xField.FieldId))
                        {
                            throw new Exception("Duplicate PlugField found for field '" + xField.FieldId + "'!");
                        }
                        xFields.Add(xField.FieldId, xField);
                    }
                    #endregion
                }
            }
        }