/// <summary> /// Initializes a new instance of the <see cref="CilGenericType"/> class. /// </summary> /// <param name="typeModule">The type module.</param> /// <param name="token">The token.</param> /// <param name="baseGenericType">Type of the base generic.</param> /// <param name="genericTypeInstanceSignature">The generic type instance signature.</param> public CilGenericType(ITypeModule typeModule, Token token, RuntimeType baseGenericType, GenericInstSigType genericTypeInstanceSignature) : base(baseGenericType.Module, token, baseGenericType.BaseType) { Debug.Assert(baseGenericType is CilRuntimeType); this.signature = genericTypeInstanceSignature; this.baseGenericType = baseGenericType as CilRuntimeType; this.InstantiationModule = typeModule; base.Attributes = baseGenericType.Attributes; base.Namespace = baseGenericType.Namespace; if (this.baseGenericType.IsNested) { // TODO: find generic type ; } // TODO: if this is a nested types, add enclosing type(s) into genericArguments first this.genericArguments = signature.GenericArguments; base.Name = GetName(typeModule); ResolveMethods(); ResolveFields(); this.containsOpenGenericArguments = CheckContainsOpenGenericParameters(); }
/// <summary> /// Patches the field. /// </summary> /// <param name="typeModule">The type module.</param> /// <param name="enclosingType">Type of the closed.</param> /// <param name="openField">The open field.</param> /// <returns></returns> RuntimeField IGenericTypePatcher.PatchField(ITypeModule typeModule, CilGenericType enclosingType, RuntimeField openField) { var openType = openField.DeclaringType as CilGenericType; var genericArguments = CloseGenericArguments(enclosingType, openType); var patchedType = GetType(openType, genericArguments); if (patchedType == null) { var typeToken = new Token(0xFE000000 | ++typeTokenCounter); var signatureToken = new Token(0xFD000000 | ++signatureTokenCounter); var sigtype = new TypeSigType(signatureToken, CilElementType.Var); var signature = new GenericInstSigType(sigtype, genericArguments); // FIXME: There has got to be a better way to do this... try { patchedType = new CilGenericType(enclosingType.Module, typeToken, openType.BaseGenericType, signature); } catch (Exception) { foreach (var module in typeModule.TypeSystem.TypeModules) { try { patchedType = new CilGenericType(module, typeToken, openType.BaseGenericType, signature); break; } catch (Exception) { ; } } } AddType(patchedType, genericArguments); } foreach (var field in patchedType.Fields) { if (field.Name == openField.Name) { return field; } } throw new MissingFieldException(); }
/// <summary> /// Closes the generic arguments. /// </summary> /// <param name="enclosingType">Type of the enclosing.</param> /// <param name="openType">Type of the open.</param> /// <returns></returns> private SigType[] CloseGenericArguments(CilGenericType enclosingType, GenericInstSigType openType) { return CloseGenericArguments(enclosingType.GenericArguments, openType.GenericArguments); }
/// <summary> /// Patches the type. /// </summary> /// <param name="typeModule">The type module.</param> /// <param name="enclosingType">Type of the enclosing.</param> /// <param name="openType">Type of the open.</param> /// <returns></returns> RuntimeType IGenericTypePatcher.PatchType(ITypeModule typeModule, CilGenericType enclosingType, CilGenericType openType) { var genericArguments = CloseGenericArguments(enclosingType, openType); var patchedType = GetType(openType, genericArguments); if (patchedType == null) { var typeToken = new Token(0xFE000000 | ++typeTokenCounter); var signatureToken = new Token(0xFD000000 | ++signatureTokenCounter); var sigtype = new TypeSigType(signatureToken, CilElementType.Var); var signature = new GenericInstSigType(sigtype, genericArguments); patchedType = new CilGenericType(enclosingType.InstantiationModule, typeToken, openType.BaseGenericType, signature); AddType(patchedType, genericArguments); } return patchedType; }
/// <summary> /// Patches the method. /// </summary> /// <param name="typeModule">The type module.</param> /// <param name="enclosingType">Type of the enclosing.</param> /// <param name="openMethod">The open method.</param> /// <returns></returns> RuntimeMethod IGenericTypePatcher.PatchMethod(ITypeModule typeModule, CilGenericType enclosingType, RuntimeMethod openMethod) { var openType = openMethod.DeclaringType as CilGenericType; var genericArguments = CloseGenericArguments(enclosingType, openType); var patchedType = GetType(openType, genericArguments); if (patchedType == null) { var typeToken = new Token(0xFE000000 | ++typeTokenCounter); var signatureToken = new Token(0xFD000000 | ++signatureTokenCounter); var sigtype = new TypeSigType(signatureToken, CilElementType.Var); var signature = new GenericInstSigType(sigtype, genericArguments); patchedType = new CilGenericType(enclosingType.InstantiationModule, typeToken, openType.BaseGenericType, signature); AddType(patchedType, genericArguments); } var methodIndex = GetMethodIndex(openMethod); return patchedType.Methods[methodIndex]; }
/// <summary> /// Patches the field. /// </summary> /// <param name="typeModule">The type module.</param> /// <param name="enclosingType">Type of the closed.</param> /// <param name="openField">The open field.</param> /// <returns></returns> RuntimeField IGenericTypePatcher.PatchField(ITypeModule typeModule, CilGenericType enclosingType, RuntimeField openField) { var openType = openField.DeclaringType as CilGenericType; var genericArguments = CloseGenericArguments(enclosingType, openType); var patchedType = GetPatchedType(openType, genericArguments); if (patchedType == null) { var typeToken = new Token(0xFE000000 | ++typeTokenCounter); var signatureToken = new Token(0xFD000000 | ++signatureTokenCounter); var sigtype = new TypeSigType(signatureToken, CilElementType.Var); var signature = new GenericInstSigType(sigtype, genericArguments); patchedType = new CilGenericType(enclosingType.InstantiationModule, typeToken, openType.BaseGenericType, signature); AddPatchedType(openType, genericArguments, patchedType); } foreach (var field in patchedType.Fields) { if (field.Name == openField.Name) { return field; } } throw new MissingFieldException(); }