Example #1
0
        public void InitializeVirtualMembers(MethodNameGroups groups, IResolver resolver)
        {
            if (initializeVirtualMembersCalled)
            {
                return;
            }
            initializeVirtualMembersCalled = true;

            foreach (var iface in interfaces)
            {
                iface.typeDef.InitializeVirtualMembers(groups, resolver);
            }
            if (baseType != null)
            {
                baseType.typeDef.InitializeVirtualMembers(groups, resolver);
            }

            foreach (var methodDef in methods.GetValues())
            {
                if (methodDef.IsVirtual())
                {
                    groups.Add(methodDef);
                }
            }

            InstantiateVirtualMembers(groups);
            InitializeInterfaceMethods(groups);
        }
Example #2
0
        public MethodNameGroups InitializeVirtualMembers()
        {
            var groups = new MethodNameGroups();

            foreach (var typeDef in allTypes)
            {
                typeDef.InitializeVirtualMembers(groups, this);
            }
            return(groups);
        }
Example #3
0
        void instantiateVirtualMembers(MethodNameGroups groups)
        {
            if (!TypeDefinition.IsInterface)
            {
                if (baseType != null)
                {
                    virtualMethodInstances.initializeFrom(baseType.typeDef.virtualMethodInstances, baseType.typeReference as GenericInstanceType);
                }

                // Figure out which methods we override in the base class
                foreach (var methodDef in methods.getValues())
                {
                    if (!methodDef.isVirtual() || methodDef.isNewSlot())
                    {
                        continue;
                    }
                    var methodInstList = virtualMethodInstances.lookup(methodDef.MethodDefinition);
                    if (methodInstList == null)
                    {
                        continue;
                    }
                    foreach (var methodInst in methodInstList)
                    {
                        groups.same(methodDef, methodInst.origMethodDef);
                    }
                }
            }

            foreach (var methodDef in methods.getValues())
            {
                if (!methodDef.isVirtual())
                {
                    continue;
                }
                virtualMethodInstances.add(new MethodInst(methodDef, methodDef.MethodDefinition));
            }
        }
Example #4
0
        void InstantiateVirtualMembers(MethodNameGroups groups)
        {
            if (!TypeDef.IsInterface)
            {
                if (baseType != null)
                {
                    virtualMethodInstances.InitializeFrom(baseType.typeDef.virtualMethodInstances, baseType.typeRef.TryGetGenericInstSig());
                }

                // Figure out which methods we override in the base class
                foreach (var methodDef in methods.GetValues())
                {
                    if (!methodDef.IsVirtual() || methodDef.IsNewSlot())
                    {
                        continue;
                    }
                    var methodInstList = virtualMethodInstances.Lookup(methodDef.MethodDef);
                    if (methodInstList == null)
                    {
                        continue;
                    }
                    foreach (var methodInst in methodInstList)
                    {
                        groups.Same(methodDef, methodInst.origMethodDef);
                    }
                }
            }

            foreach (var methodDef in methods.GetValues())
            {
                if (!methodDef.IsVirtual())
                {
                    continue;
                }
                virtualMethodInstances.Add(new MethodInst(methodDef, methodDef.MethodDef));
            }
        }
Example #5
0
		void PrepareRenameMemberDefs(MethodNameGroups groups) {
			if (isVerbose)
				Logger.v("Renaming member definitions #1");

			PrepareRenameEntryPoints();

			var virtualMethods = new GroupHelper(memberInfos, modules.AllTypes);
			var ifaceMethods = new GroupHelper(memberInfos, modules.AllTypes);
			var propMethods = new GroupHelper(memberInfos, modules.AllTypes);
			var eventMethods = new GroupHelper(memberInfos, modules.AllTypes);
			foreach (var group in GetSorted(groups)) {
				if (group.HasNonRenamableMethod())
					continue;
				else if (group.HasGetterOrSetterPropertyMethod() && GetPropertyMethodType(group.Methods[0]) != PropertyMethodType.Other)
					propMethods.Add(group);
				else if (group.HasAddRemoveOrRaiseEventMethod())
					eventMethods.Add(group);
				else if (group.HasInterfaceMethod())
					ifaceMethods.Add(group);
				else
					virtualMethods.Add(group);
			}

			var prepareHelper = new PrepareHelper(memberInfos, modules.AllTypes);
			prepareHelper.Prepare((info) => info.PrepareRenameMembers());

			prepareHelper.Prepare((info) => info.PrepareRenamePropsAndEvents());
			propMethods.VisitAll((group) => PrepareRenameProperty(group, false));
			eventMethods.VisitAll((group) => PrepareRenameEvent(group, false));
			propMethods.VisitAll((group) => PrepareRenameProperty(group, true));
			eventMethods.VisitAll((group) => PrepareRenameEvent(group, true));

			foreach (var typeDef in modules.AllTypes)
				memberInfos.Type(typeDef).InitializeEventHandlerNames();

			prepareHelper.Prepare((info) => info.PrepareRenameMethods());
			ifaceMethods.VisitAll((group) => PrepareRenameVirtualMethods(group, "imethod_", false));
			virtualMethods.VisitAll((group) => PrepareRenameVirtualMethods(group, "vmethod_", false));
			ifaceMethods.VisitAll((group) => PrepareRenameVirtualMethods(group, "imethod_", true));
			virtualMethods.VisitAll((group) => PrepareRenameVirtualMethods(group, "vmethod_", true));

			RestoreMethodArgs(groups);

			foreach (var typeDef in modules.AllTypes)
				memberInfos.Type(typeDef).PrepareRenameMethods2();
		}
Example #6
0
        void InitializeInterfaceMethods(MethodNameGroups groups)
        {
            InitializeAllInterfaces();

            if (TypeDef.IsInterface)
            {
                return;
            }

            //--- Partition II 12.2 Implementing virtual methods on interfaces:
            //--- The VES shall use the following algorithm to determine the appropriate
            //--- implementation of an interface's virtual abstract methods:
            //---
            //--- * If the base class implements the interface, start with the same virtual methods
            //---	that it provides; otherwise, create an interface that has empty slots for all
            //---	virtual functions.
            // Done. See initializeAllInterfaces().

            var methodsDict = new Dictionary <IMethodDefOrRef, MMethodDef>(MethodEqualityComparer.DontCompareDeclaringTypes);

            //--- * If this class explicitly specifies that it implements the interface (i.e., the
            //---	interfaces that appear in this class‘ InterfaceImpl table, §22.23)
            //---	* If the class defines any public virtual newslot methods whose name and
            //---	  signature match a virtual method on the interface, then use these new virtual
            //---	  methods to implement the corresponding interface method.
            if (interfaces.Count > 0)
            {
                methodsDict.Clear();
                foreach (var method in methods.GetValues())
                {
                    if (!method.IsPublic() || !method.IsVirtual() || !method.IsNewSlot())
                    {
                        continue;
                    }
                    methodsDict[method.MethodDef] = method;
                }

                foreach (var ifaceInfo in interfaces)
                {
                    foreach (var methodsList in ifaceInfo.typeDef.virtualMethodInstances.GetMethods())
                    {
                        if (methodsList.Count < 1)
                        {
                            continue;
                        }
                        var methodInst  = methodsList[0];
                        var ifaceMethod = methodInst.origMethodDef;
                        if (!ifaceMethod.IsVirtual())
                        {
                            continue;
                        }
                        var        ifaceMethodRef = GenericArgsSubstitutor.Create(methodInst.methodRef, ifaceInfo.typeRef.TryGetGenericInstSig());
                        MMethodDef classMethod;
                        if (!methodsDict.TryGetValue(ifaceMethodRef, out classMethod))
                        {
                            continue;
                        }
                        interfaceMethodInfos.AddMethod(ifaceInfo, ifaceMethod, classMethod);
                    }
                }
            }

            //--- * If there are any virtual methods in the interface that still have empty slots,
            //---	see if there are any public virtual methods, but not public virtual newslot
            //---	methods, available on this class (directly or inherited) having the same name
            //---	and signature, then use these to implement the corresponding methods on the
            //---	interface.
            methodsDict.Clear();
            foreach (var methodInstList in virtualMethodInstances.GetMethods())
            {
                // This class' method is at the end
                for (int i = methodInstList.Count - 1; i >= 0; i--)
                {
                    var classMethod = methodInstList[i];
                    // These methods are guaranteed to be virtual.
                    // We should allow newslot methods, despite what the official doc says.
                    if (!classMethod.origMethodDef.IsPublic())
                    {
                        continue;
                    }
                    methodsDict[classMethod.methodRef] = classMethod.origMethodDef;
                    break;
                }
            }
            foreach (var ifaceInfo in allImplementedInterfaces.Keys)
            {
                foreach (var methodsList in ifaceInfo.typeDef.virtualMethodInstances.GetMethods())
                {
                    if (methodsList.Count < 1)
                    {
                        continue;
                    }
                    var ifaceMethod = methodsList[0].origMethodDef;
                    if (!ifaceMethod.IsVirtual())
                    {
                        continue;
                    }
                    var        ifaceMethodRef = GenericArgsSubstitutor.Create(ifaceMethod.MethodDef, ifaceInfo.typeRef.TryGetGenericInstSig());
                    MMethodDef classMethod;
                    if (!methodsDict.TryGetValue(ifaceMethodRef, out classMethod))
                    {
                        continue;
                    }
                    interfaceMethodInfos.AddMethodIfEmpty(ifaceInfo, ifaceMethod, classMethod);
                }
            }

            //--- * Apply all MethodImpls that are specified for this class, thereby placing
            //---	explicitly specified virtual methods into the interface in preference to those
            //---	inherited or chosen by name matching.
            methodsDict.Clear();
            var ifaceMethodsDict = new Dictionary <IMethodDefOrRef, MMethodDef>(MethodEqualityComparer.CompareDeclaringTypes);

            foreach (var ifaceInfo in allImplementedInterfaces.Keys)
            {
                var git = ifaceInfo.typeRef.TryGetGenericInstSig();
                foreach (var ifaceMethod in ifaceInfo.typeDef.methods.GetValues())
                {
                    IMethodDefOrRef ifaceMethodRef = ifaceMethod.MethodDef;
                    if (git != null)
                    {
                        ifaceMethodRef = SimpleClone(ifaceMethod.MethodDef, ifaceInfo.typeRef);
                    }
                    ifaceMethodsDict[ifaceMethodRef] = ifaceMethod;
                }
            }
            foreach (var classMethod in methods.GetValues())
            {
                if (!classMethod.IsVirtual())
                {
                    continue;
                }
                foreach (var overrideMethod in classMethod.MethodDef.Overrides)
                {
                    MMethodDef ifaceMethod;
                    if (!ifaceMethodsDict.TryGetValue(overrideMethod.MethodDeclaration, out ifaceMethod))
                    {
                        // We couldn't find the interface method (eg. interface not resolved) or
                        // it overrides a base class method, and not an interface method.
                        continue;
                    }

                    interfaceMethodInfos.AddMethod(overrideMethod.MethodDeclaration.DeclaringType, ifaceMethod, classMethod);
                }
            }

            //--- * If the current class is not abstract and there are any interface methods that
            //---	still have empty slots, then the program is invalid.
            // Check it anyway. C# requires a method, even if it's abstract. I don't think anyone
            // writes pure CIL assemblies.
            foreach (var info in interfaceMethodInfos.AllInfos)
            {
                foreach (var pair in info.IfaceMethodToClassMethod)
                {
                    if (pair.Value != null)
                    {
                        continue;
                    }
                    if (!ResolvedAllInterfaces() || !ResolvedBaseClasses())
                    {
                        continue;
                    }
                    // Ignore if COM class
                    if (!TypeDef.IsImport &&
                        !HasAttribute("System.Runtime.InteropServices.ComImportAttribute") &&
                        !HasAttribute("System.Runtime.InteropServices.TypeLibTypeAttribute"))
                    {
                        Logger.w("Could not find interface method {0} ({1:X8}). Type: {2} ({3:X8})",
                                 Utils.RemoveNewlines(pair.Key.methodDef.MethodDef),
                                 pair.Key.methodDef.MethodDef.MDToken.ToInt32(),
                                 Utils.RemoveNewlines(TypeDef),
                                 TypeDef.MDToken.ToInt32());
                    }
                }
            }

            foreach (var info in interfaceMethodInfos.AllInfos)
            {
                foreach (var pair in info.IfaceMethodToClassMethod)
                {
                    if (pair.Value == null)
                    {
                        continue;
                    }
                    if (pair.Key.methodDef.MethodDef.Name != pair.Value.MethodDef.Name)
                    {
                        continue;
                    }
                    groups.Same(pair.Key.methodDef, pair.Value);
                }
            }
        }
Example #7
0
		void RestorePropertiesAndEvents(MethodNameGroups groups) {
			var allGroups = groups.GetAllGroups();
			RestoreVirtualProperties(allGroups);
			RestorePropertiesFromNames2(allGroups);
			ResetVirtualPropertyNames(allGroups);
			RestoreVirtualEvents(allGroups);
			RestoreEventsFromNames2(allGroups);
			ResetVirtualEventNames(allGroups);
		}
Example #8
0
 void restorePropertiesAndEvents(MethodNameGroups groups)
 {
     var allGroups = groups.getAllGroups();
     restoreVirtualProperties(allGroups);
     restorePropertiesFromNames(allGroups);
     restoreVirtualEvents(allGroups);
     restoreEventsFromNames(allGroups);
 }
Example #9
0
		static List<MethodNameGroup> GetSorted(MethodNameGroups groups) {
			var allGroups = new List<MethodNameGroup>(groups.GetAllGroups());
			allGroups.Sort((a, b) => b.Count.CompareTo(a.Count));
			return allGroups;
		}
Example #10
0
		void RemoveUselessOverrides(MethodNameGroups groups) {
			foreach (var group in groups.GetAllGroups()) {
				foreach (var method in group.Methods) {
					if (!method.Owner.HasModule)
						continue;
					if (!method.IsPublic())
						continue;
					var overrides = method.MethodDef.Overrides;
					for (int i = 0; i < overrides.Count; i++) {
						var overrideMethod = overrides[i].MethodDeclaration;
						if (method.MethodDef.Name != overrideMethod.Name)
							continue;
						if (isVerbose)
							Logger.v("Removed useless override from method {0} ({1:X8}), override: {2:X8}",
									Utils.RemoveNewlines(method.MethodDef),
									method.MethodDef.MDToken.ToInt32(),
									overrideMethod.MDToken.ToInt32());
						overrides.RemoveAt(i);
						i--;
					}
				}
			}
		}
Example #11
0
        void instantiateVirtualMembers(MethodNameGroups groups)
        {
            if (!TypeDefinition.IsInterface) {
                if (baseType != null)
                    virtualMethodInstances.initializeFrom(baseType.typeDef.virtualMethodInstances, baseType.typeReference as GenericInstanceType);

                // Figure out which methods we override in the base class
                foreach (var methodDef in methods.getValues()) {
                    if (!methodDef.isVirtual() || methodDef.isNewSlot())
                        continue;
                    var methodInstList = virtualMethodInstances.lookup(methodDef.MethodDefinition);
                    if (methodInstList == null)
                        continue;
                    foreach (var methodInst in methodInstList)
                        groups.same(methodDef, methodInst.origMethodDef);
                }
            }

            foreach (var methodDef in methods.getValues()) {
                if (!methodDef.isVirtual())
                    continue;
                virtualMethodInstances.add(new MethodInst(methodDef, methodDef.MethodDefinition));
            }
        }
Example #12
0
		void RestoreMethodArgs(MethodNameGroups groups) {
			foreach (var group in groups.GetAllGroups()) {
				if (group.Methods[0].VisibleParameterCount == 0)
					continue;

				var argNames = GetValidArgNames(group);

				foreach (var method in group.Methods) {
					if (!method.Owner.HasModule)
						continue;
					var nameChecker = method.Owner.Module.ObfuscatedFile.NameChecker;

					for (int i = 0; i < argNames.Length; i++) {
						var argName = argNames[i];
						if (argName == null || !nameChecker.IsValidMethodArgName(argName))
							continue;
						var info = memberInfos.Param(method.ParamDefs[i]);
						if (nameChecker.IsValidMethodArgName(info.oldName))
							continue;
						info.newName = argName;
					}
				}
			}
		}
Example #13
0
 static List<MethodNameGroup> getSorted(MethodNameGroups groups)
 {
     var allGroups = new List<MethodNameGroup>(groups.getAllGroups());
     allGroups.Sort((a, b) => Utils.compareInt32(b.Count, a.Count));
     return allGroups;
 }
Example #14
0
 void removeUselessOverrides(MethodNameGroups groups)
 {
     foreach (var group in groups.getAllGroups()) {
         foreach (var method in group.Methods) {
             if (!method.Owner.HasModule)
                 continue;
             if (!method.isPublic())
                 continue;
             var overrides = method.MethodDefinition.Overrides;
             for (int i = 0; i < overrides.Count; i++) {
                 var overrideMethod = overrides[i];
                 if (method.MethodDefinition.Name != overrideMethod.Name)
                     continue;
                 Log.v("Removed useless override from method {0} ({1:X8}), override: {2:X8}",
                             Utils.removeNewlines(method.MethodDefinition),
                             method.MethodDefinition.MetadataToken.ToInt32(),
                             overrideMethod.MetadataToken.ToInt32());
                 overrides.RemoveAt(i);
                 i--;
             }
         }
     }
 }
Example #15
0
		void InstantiateVirtualMembers(MethodNameGroups groups) {
			if (!TypeDef.IsInterface) {
				if (baseType != null)
					virtualMethodInstances.InitializeFrom(baseType.typeDef.virtualMethodInstances, baseType.typeRef.TryGetGenericInstSig());

				// Figure out which methods we override in the base class
				foreach (var methodDef in methods.GetValues()) {
					if (!methodDef.IsVirtual() || methodDef.IsNewSlot())
						continue;
					var methodInstList = virtualMethodInstances.Lookup(methodDef.MethodDef);
					if (methodInstList == null)
						continue;
					foreach (var methodInst in methodInstList)
						groups.Same(methodDef, methodInst.origMethodDef);
				}
			}

			foreach (var methodDef in methods.GetValues()) {
				if (!methodDef.IsVirtual())
					continue;
				virtualMethodInstances.Add(new MethodInst(methodDef, methodDef.MethodDef));
			}
		}
Example #16
0
		void InitializeInterfaceMethods(MethodNameGroups groups) {
			InitializeAllInterfaces();

			if (TypeDef.IsInterface)
				return;

			//--- Partition II 12.2 Implementing virtual methods on interfaces:
			//--- The VES shall use the following algorithm to determine the appropriate
			//--- implementation of an interface's virtual abstract methods:
			//---
			//--- * If the base class implements the interface, start with the same virtual methods
			//---	that it provides; otherwise, create an interface that has empty slots for all
			//---	virtual functions.
			// Done. See initializeAllInterfaces().

			var methodsDict = new Dictionary<IMethodDefOrRef, MMethodDef>(MethodEqualityComparer.DontCompareDeclaringTypes);

			//--- * If this class explicitly specifies that it implements the interface (i.e., the
			//---	interfaces that appear in this class‘ InterfaceImpl table, §22.23)
			//---	* If the class defines any public virtual newslot methods whose name and
			//---	  signature match a virtual method on the interface, then use these new virtual
			//---	  methods to implement the corresponding interface method.
			if (interfaces.Count > 0) {
				methodsDict.Clear();
				foreach (var method in methods.GetValues()) {
					if (!method.IsPublic() || !method.IsVirtual() || !method.IsNewSlot())
						continue;
					methodsDict[method.MethodDef] = method;
				}

				foreach (var ifaceInfo in interfaces) {
					foreach (var methodsList in ifaceInfo.typeDef.virtualMethodInstances.GetMethods()) {
						if (methodsList.Count < 1)
							continue;
						var methodInst = methodsList[0];
						var ifaceMethod = methodInst.origMethodDef;
						if (!ifaceMethod.IsVirtual())
							continue;
						var ifaceMethodRef = GenericArgsSubstitutor.Create(methodInst.methodRef, ifaceInfo.typeRef.TryGetGenericInstSig());
						MMethodDef classMethod;
						if (!methodsDict.TryGetValue(ifaceMethodRef, out classMethod))
							continue;
						interfaceMethodInfos.AddMethod(ifaceInfo, ifaceMethod, classMethod);
					}
				}
			}

			//--- * If there are any virtual methods in the interface that still have empty slots,
			//---	see if there are any public virtual methods, but not public virtual newslot
			//---	methods, available on this class (directly or inherited) having the same name
			//---	and signature, then use these to implement the corresponding methods on the
			//---	interface.
			methodsDict.Clear();
			foreach (var methodInstList in virtualMethodInstances.GetMethods()) {
				// This class' method is at the end
				for (int i = methodInstList.Count - 1; i >= 0; i--) {
					var classMethod = methodInstList[i];
					// These methods are guaranteed to be virtual.
					// We should allow newslot methods, despite what the official doc says.
					if (!classMethod.origMethodDef.IsPublic())
						continue;
					methodsDict[classMethod.methodRef] = classMethod.origMethodDef;
					break;
				}
			}
			foreach (var ifaceInfo in allImplementedInterfaces.Keys) {
				foreach (var methodsList in ifaceInfo.typeDef.virtualMethodInstances.GetMethods()) {
					if (methodsList.Count < 1)
						continue;
					var ifaceMethod = methodsList[0].origMethodDef;
					if (!ifaceMethod.IsVirtual())
						continue;
					var ifaceMethodRef = GenericArgsSubstitutor.Create(ifaceMethod.MethodDef, ifaceInfo.typeRef.TryGetGenericInstSig());
					MMethodDef classMethod;
					if (!methodsDict.TryGetValue(ifaceMethodRef, out classMethod))
						continue;
					interfaceMethodInfos.AddMethodIfEmpty(ifaceInfo, ifaceMethod, classMethod);
				}
			}

			//--- * Apply all MethodImpls that are specified for this class, thereby placing
			//---	explicitly specified virtual methods into the interface in preference to those
			//---	inherited or chosen by name matching.
			methodsDict.Clear();
			var ifaceMethodsDict = new Dictionary<IMethodDefOrRef, MMethodDef>(MethodEqualityComparer.CompareDeclaringTypes);
			foreach (var ifaceInfo in allImplementedInterfaces.Keys) {
				var git = ifaceInfo.typeRef.TryGetGenericInstSig();
				foreach (var ifaceMethod in ifaceInfo.typeDef.methods.GetValues()) {
					IMethodDefOrRef ifaceMethodRef = ifaceMethod.MethodDef;
					if (git != null)
						ifaceMethodRef = SimpleClone(ifaceMethod.MethodDef, ifaceInfo.typeRef);
					ifaceMethodsDict[ifaceMethodRef] = ifaceMethod;
				}
			}
			foreach (var classMethod in methods.GetValues()) {
				if (!classMethod.IsVirtual())
					continue;
				foreach (var overrideMethod in classMethod.MethodDef.Overrides) {
					MMethodDef ifaceMethod;
					if (!ifaceMethodsDict.TryGetValue(overrideMethod.MethodDeclaration, out ifaceMethod)) {
						// We couldn't find the interface method (eg. interface not resolved) or
						// it overrides a base class method, and not an interface method.
						continue;
					}

					interfaceMethodInfos.AddMethod(overrideMethod.MethodDeclaration.DeclaringType, ifaceMethod, classMethod);
				}
			}

			//--- * If the current class is not abstract and there are any interface methods that
			//---	still have empty slots, then the program is invalid.
			// Check it anyway. C# requires a method, even if it's abstract. I don't think anyone
			// writes pure CIL assemblies.
			foreach (var info in interfaceMethodInfos.AllInfos) {
				foreach (var pair in info.IfaceMethodToClassMethod) {
					if (pair.Value != null)
						continue;
					if (!ResolvedAllInterfaces() || !ResolvedBaseClasses())
						continue;
					// Ignore if COM class
					if (!TypeDef.IsImport &&
						!HasAttribute("System.Runtime.InteropServices.ComImportAttribute") &&
						!HasAttribute("System.Runtime.InteropServices.TypeLibTypeAttribute")) {
						Logger.w("Could not find interface method {0} ({1:X8}). Type: {2} ({3:X8})",
								Utils.RemoveNewlines(pair.Key.methodDef.MethodDef),
								pair.Key.methodDef.MethodDef.MDToken.ToInt32(),
								Utils.RemoveNewlines(TypeDef),
								TypeDef.MDToken.ToInt32());
					}
				}
			}

			foreach (var info in interfaceMethodInfos.AllInfos) {
				foreach (var pair in info.IfaceMethodToClassMethod) {
					if (pair.Value == null)
						continue;
					if (pair.Key.methodDef.MethodDef.Name != pair.Value.MethodDef.Name)
						continue;
					groups.Same(pair.Key.methodDef, pair.Value);
				}
			}
		}
Example #17
0
		public void InitializeVirtualMembers(MethodNameGroups groups, IResolver resolver) {
			if (initializeVirtualMembersCalled)
				return;
			initializeVirtualMembersCalled = true;

			foreach (var iface in interfaces)
				iface.typeDef.InitializeVirtualMembers(groups, resolver);
			if (baseType != null)
				baseType.typeDef.InitializeVirtualMembers(groups, resolver);

			foreach (var methodDef in methods.GetValues()) {
				if (methodDef.IsVirtual())
					groups.Add(methodDef);
			}

			InstantiateVirtualMembers(groups);
			InitializeInterfaceMethods(groups);
		}