示例#1
0
        private void BuildCacheFor(MethodBase m, MethodBaseCache.SpecialMethodEnum methodType, EventInfo ev, params MemberInfo[] addFor)
        {
            MethodBaseCache cacheForM = ((MethodBaseCache)GetMemberCache(m));

            // check if method is used in a special context (property/event)
            if (cacheForM.MethodType == MethodBaseCache.SpecialMethodEnum.None && methodType != MethodBaseCache.SpecialMethodEnum.None)
            {
                cacheForM.MethodType = methodType;
            }
            cacheForM.SpecialReference = ev;

            BuildCacheFor(m, methodType, addFor);
        }
示例#2
0
 public MemberCache GetMemberCache(MemberInfo member)
 {
     lock (lockMethodCache)
     {
         MemberCache c;
         if (!memberCache.TryGetValue(new Member(member), out c))
         {
             if (member is FieldInfo)
             {
                 memberCache.Add(new Member(member), c = new FieldCache(member));
             }
             else if (member is MethodBase)
             {
                 memberCache.Add(new Member(member), c = new MethodBaseCache(member));
             }
             else
             {
                 memberCache.Add(new Member(member), c = new MemberCache(member));
             }
         }
         return(c);
     }
 }
示例#3
0
        private void BuildCacheFor(MethodBase m, MethodBaseCache.SpecialMethodEnum methodType, params MemberInfo[] addFor)
        {
            MethodBaseCache cacheForM = ((MethodBaseCache)GetMemberCache(m));

            // check if method is used in a special context (property/event)
            if (cacheForM.MethodType == MethodBaseCache.SpecialMethodEnum.None && methodType != MethodBaseCache.SpecialMethodEnum.None)
            {
                cacheForM.MethodType = methodType;
            }

            foreach (var p in m.GetParameters())
            {
                if (!p.ParameterType.IsGenericParameter)
                {
                    GetTypeCache(p.ParameterType).AddUsedBy(addFor);
                }
            }

            if (m is MethodInfo)
            {
                GetTypeCache(((MethodInfo)m).ReturnType).AddUsedBy(addFor);
            }

            try
            {
                foreach (var i in m.GetILInstructions())
                {
                    if (i.Operand is MemberInfo)
                    {
                        var cache = GetMemberCache((MemberInfo)i.Operand);

                        foreach (var memberToAddFor in addFor)
                        {
                            cache.AddUsedBy(memberToAddFor, i.Offset);
                        }

                        cacheForM.AddUses((MemberInfo)i.Operand, i.Offset);

                        if (i.Code == OpCodes.Call || i.Code == OpCodes.Callvirt)
                        {
                            ((MethodBaseCache)cache).AddCalledBy(addFor);
                        }
                        else if (i.Code == OpCodes.Stfld)
                        {
                            ((FieldCache)cache).AddAssignedBy(addFor);
                        }
                        else if (i.Code == OpCodes.Ldfld)
                        {
                            ((FieldCache)cache).AddReadBy(addFor);
                        }
                        else if (i.Code == OpCodes.Ldftn) // event wiring in c# uses ldftn to pass methods to the handler delegate constructor
                        {
                            // read as pointer, possibly for event
                            if (i.Operand is MethodBase && i.Next.Code == OpCodes.Newobj && (i.Next.Next.Code == OpCodes.Callvirt || i.Next.Next.Code == OpCodes.Call))
                            {
                                var addMethod      = (MethodInfo)i.Next.Next.Operand;
                                var addMethodCache = GetMemberCache(addMethod);

                                MemberInfo source = null;
                                if (i.Previous.Previous.Code == OpCodes.Ldfld)
                                {
                                    source = (FieldInfo)i.Previous.Previous.Operand;
                                }
                                else if (i.Previous.Previous.Code == OpCodes.Call || i.Previous.Previous.Code == OpCodes.Callvirt)
                                {
                                    source = (MethodInfo)i.Previous.Previous.Operand;
                                }

                                if (source != null)
                                {
                                    // todo add event info to source
                                }
                                ((MethodBaseCache)cache).AddWiredForEvent(new WiredLookupEntry(addMethod, source));
                                ((MethodBaseCache)addMethodCache).AddWiresEvent(new WiredLookupEntry((MethodInfo)i.Operand, source));
                            }
                        }
                        else if (i.Code == OpCodes.Ldvirtftn) // VB.NET uses event wiring in a property setter
                        {
                            if (i.Operand is MethodBase && i.Next.Code == OpCodes.Newobj)
                            {
                                var nextnext = i.Next.Next;

                                int idxOfEventLocal = -1;
                                if (nextnext.Code == OpCodes.Stloc || nextnext.Code == OpCodes.Stloc_S)
                                {
                                    idxOfEventLocal = (int)nextnext.Operand;
                                }
                                else if (nextnext.Code == OpCodes.Stloc_0)
                                {
                                    idxOfEventLocal = 0;
                                }
                                else if (nextnext.Code == OpCodes.Stloc_1)
                                {
                                    idxOfEventLocal = 1;
                                }
                                else if (nextnext.Code == OpCodes.Stloc_2)
                                {
                                    idxOfEventLocal = 2;
                                }
                                else if (nextnext.Code == OpCodes.Stloc_3)
                                {
                                    idxOfEventLocal = 3;
                                }

                                if (idxOfEventLocal != -1)
                                {
                                    // go find the ldloc

                                    ILInstruction curInstr = i;
                                    while (curInstr != null)
                                    {
                                        if ((((curInstr.Code == OpCodes.Ldloc || curInstr.Code == OpCodes.Ldloc_S) && (int)curInstr.Operand == idxOfEventLocal) ||
                                             (curInstr.Code == OpCodes.Ldloc_0 && idxOfEventLocal == 0) ||
                                             (curInstr.Code == OpCodes.Ldloc_1 && idxOfEventLocal == 1) ||
                                             (curInstr.Code == OpCodes.Ldloc_2 && idxOfEventLocal == 2) ||
                                             (curInstr.Code == OpCodes.Ldloc_3 && idxOfEventLocal == 3))
                                            &&
                                            (curInstr.Next.Code == OpCodes.Call || curInstr.Next.Code == OpCodes.Callvirt) &&
                                            curInstr.Previous.Code == OpCodes.Ldfld &&
                                            ((MethodInfo)curInstr.Next.Operand).Name.StartsWith("add_"))
                                        {
                                            MemberInfo source         = (MemberInfo)curInstr.Previous.Operand;
                                            var        addMethod      = (MethodInfo)curInstr.Next.Operand;
                                            var        addMethodCache = GetMemberCache(addMethod);


                                            if (source != null)
                                            {
                                                // todo add event info to source
                                            }
                                            ((MethodBaseCache)cache).AddWiredForEvent(new WiredLookupEntry(addMethod, source));
                                            ((MethodBaseCache)addMethodCache).AddWiresEvent(new WiredLookupEntry((MethodInfo)i.Operand, source));
                                            break;
                                        }

                                        curInstr = curInstr.Next;
                                    }
                                }
                            }
                        }
                        else if (i.Code == OpCodes.Newobj)
                        {
                            GetTypeCache(((ConstructorInfo)i.Operand).DeclaringType).AddCreatedBy(addFor);
                        }
                    }

                    if (i.Code == OpCodes.Ldstr)
                    {
                        cacheForM.AddUsedString((string)i.Operand);
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Unable to build analysis cache for " + m.ToSignatureString() + ", error: " + ex.GetType().FullName + " - " + ex.Message);
            }
        }