/// <summary>
		/// Reads a method body
		/// </summary>
		/// <param name="method">Method</param>
		/// <param name="row">Method's row</param>
		/// <returns>A <see cref="MethodBody"/> or <c>null</c> if none</returns>
		internal MethodBody ReadMethodBody(MethodDefMD method, RawMethodRow row) {
			MethodBody mb;
			var mDec = methodDecrypter;
			if (mDec != null && mDec.GetMethodBody(method.Rid, (RVA)row.RVA, method.Parameters, out mb))
				return mb;

			if (row.RVA == 0)
				return null;
			var codeType = (MethodImplAttributes)row.ImplFlags & MethodImplAttributes.CodeTypeMask;
			if (codeType == MethodImplAttributes.IL)
				return ReadCilBody(method.Parameters, (RVA)row.RVA);
			if (codeType == MethodImplAttributes.Native)
				return new NativeMethodBody((RVA)row.RVA);
			return null;
		}
		/// <summary>
		/// Reads a method body
		/// </summary>
		/// <param name="method">Method</param>
		/// <param name="row">Method's row</param>
		/// <returns>A <see cref="MethodBody"/> or <c>null</c> if none</returns>
		internal MethodBody ReadMethodBody(MethodDefMD method, RawMethodRow row) {
			if (methodDecrypter != null && methodDecrypter.HasMethodBody(method.Rid))
				return methodDecrypter.GetMethodBody(method.Rid, (RVA)row.RVA, method.Parameters);

			if (row.RVA == 0)
				return null;
			var codeType = ((MethodImplAttributes)row.ImplFlags & MethodImplAttributes.CodeTypeMask);
			if (codeType == MethodImplAttributes.IL)
				return ReadCilBody(method.Parameters, (RVA)row.RVA);
			if (codeType == MethodImplAttributes.Native)
				return new NativeMethodBody((RVA)row.RVA);
			return null;
		}
		/// <inheritdoc/>
		protected override void AllocateMemberDefRids() {
			int numTypes = allTypeDefs.Count;
			int typeNum = 0;
			int notifyNum = 0;
			const int numNotifyEvents = 5; // AllocateMemberDefRids0 - AllocateMemberDefRids4
			int notifyAfter = numTypes / numNotifyEvents;

			uint fieldListRid = 1, methodListRid = 1;
			uint eventListRid = 1, propertyListRid = 1;
			uint paramListRid = 1;
			foreach (var type in allTypeDefs) {
				if (typeNum++ == notifyAfter && notifyNum < numNotifyEvents) {
					Listener.OnMetaDataEvent(this, MetaDataEvent.AllocateMemberDefRids0 + notifyNum++);
					notifyAfter += numTypes / numNotifyEvents;
				}

				if (type == null)
					continue;
				uint typeRid = GetRid(type);
				var typeRow = tablesHeap.TypeDefTable[typeRid];
				typeRow.FieldList = fieldListRid;
				typeRow.MethodList = methodListRid;

				foreach (var field in type.Fields) {
					if (field == null)
						continue;
					uint rid = fieldListRid++;
					if (rid != tablesHeap.FieldTable.Create(new RawFieldRow()))
						throw new ModuleWriterException("Invalid field rid");
					fieldDefInfos.Add(field, rid);
				}

				foreach (var method in type.Methods) {
					if (method == null)
						continue;
					uint rid = methodListRid++;
					var row = new RawMethodRow(0, 0, 0, 0, 0, paramListRid);
					if (rid != tablesHeap.MethodTable.Create(row))
						throw new ModuleWriterException("Invalid method rid");
					methodDefInfos.Add(method, rid);
					foreach (var pd in Sort(method.ParamDefs)) {
						if (pd == null)
							continue;
						uint pdRid = paramListRid++;
						if (pdRid != tablesHeap.ParamTable.Create(new RawParamRow()))
							throw new ModuleWriterException("Invalid param rid");
						paramDefInfos.Add(pd, pdRid);
					}
				}

				if (!IsEmpty(type.Events)) {
					uint eventMapRid = tablesHeap.EventMapTable.Create(new RawEventMapRow(typeRid, eventListRid));
					eventMapInfos.Add(type, eventMapRid);
					foreach (var evt in type.Events) {
						if (evt == null)
							continue;
						uint rid = eventListRid++;
						if (rid != tablesHeap.EventTable.Create(new RawEventRow()))
							throw new ModuleWriterException("Invalid event rid");
						eventDefInfos.Add(evt, rid);
					}
				}

				if (!IsEmpty(type.Properties)) {
					uint propertyMapRid = tablesHeap.PropertyMapTable.Create(new RawPropertyMapRow(typeRid, propertyListRid));
					propertyMapInfos.Add(type, propertyMapRid);
					foreach (var prop in type.Properties) {
						if (prop == null)
							continue;
						uint rid = propertyListRid++;
						if (rid != tablesHeap.PropertyTable.Create(new RawPropertyRow()))
							throw new ModuleWriterException("Invalid property rid");
						propertyDefInfos.Add(prop, rid);
					}
				}
			}
			while (notifyNum < numNotifyEvents)
				Listener.OnMetaDataEvent(this, MetaDataEvent.AllocateMemberDefRids0 + notifyNum++);
		}
		/// <inheritdoc/>
		protected override void AllocateMemberDefRids() {
			uint fieldListRid = 1, methodListRid = 1;
			uint eventListRid = 1, propertyListRid = 1;
			uint paramListRid = 1;
			foreach (var type in allTypeDefs) {
				if (type == null)
					continue;
				uint typeRid = GetRid(type);
				var typeRow = tablesHeap.TypeDefTable[typeRid];
				typeRow.FieldList = fieldListRid;
				typeRow.MethodList = methodListRid;

				foreach (var field in type.Fields) {
					if (field == null)
						continue;
					uint rid = fieldListRid++;
					if (rid != tablesHeap.FieldTable.Create(new RawFieldRow()))
						throw new ModuleWriterException("Invalid field rid");
					fieldDefInfos.Add(field, rid);
				}

				foreach (var method in type.Methods) {
					if (method == null)
						continue;
					uint rid = methodListRid++;
					var row = new RawMethodRow(0, 0, 0, 0, 0, paramListRid);
					if (rid != tablesHeap.MethodTable.Create(row))
						throw new ModuleWriterException("Invalid method rid");
					methodDefInfos.Add(method, rid);
					foreach (var pd in Sort(method.ParamDefs)) {
						if (pd == null)
							continue;
						uint pdRid = paramListRid++;
						if (pdRid != tablesHeap.ParamTable.Create(new RawParamRow()))
							throw new ModuleWriterException("Invalid param rid");
						paramDefInfos.Add(pd, pdRid);
					}
				}

				if (!IsEmpty(type.Events)) {
					uint eventMapRid = tablesHeap.EventMapTable.Create(new RawEventMapRow(typeRid, eventListRid));
					eventMapInfos.Add(type, eventMapRid);
					foreach (var evt in type.Events) {
						if (evt == null)
							continue;
						uint rid = eventListRid++;
						if (rid != tablesHeap.EventTable.Create(new RawEventRow()))
							throw new ModuleWriterException("Invalid event rid");
						eventDefInfos.Add(evt, rid);
					}
				}

				if (!IsEmpty(type.Properties)) {
					uint propertyMapRid = tablesHeap.PropertyMapTable.Create(new RawPropertyMapRow(typeRid, propertyListRid));
					propertyMapInfos.Add(type, propertyMapRid);
					foreach (var prop in type.Properties) {
						if (prop == null)
							continue;
						uint rid = propertyListRid++;
						if (rid != tablesHeap.PropertyTable.Create(new RawPropertyRow()))
							throw new ModuleWriterException("Invalid property rid");
						propertyDefInfos.Add(prop, rid);
					}
				}
			}
		}