(TypeMirror type, bool containsGenericParameters) Create(DmdType type) { if ((object)type == null) { throw new ArgumentNullException(nameof(type)); } if (typeCache.TryGetType(type, out var cachedType)) { return(cachedType, false); } if (recursionCounter++ > 100) { throw new InvalidOperationException(); } (TypeMirror type, bool containsGenericParameters)result; bool addType = true; switch (type.TypeSignatureKind) { case DmdTypeSignatureKind.Type: if (!engine.TryGetMonoModule(type.Module.GetDebuggerModule() ?? throw new InvalidOperationException(), out var monoModule)) { throw new InvalidOperationException(); } Debug.Assert((type.MetadataToken >> 24) == 0x02); //TODO: This can sometimes crash Unity's old mono fork //TODO: It's possible to resolve types, but it's an internal method and it requires a method in the module result = (monoModule.Assembly.GetType(type.FullName, false, false), false); if (result.type == null) { throw new InvalidOperationException(); } if (result.type.MetadataToken != type.MetadataToken) { throw new InvalidOperationException(); } break; case DmdTypeSignatureKind.Pointer: result = Create(type.GetElementType()); result = (TryResolveType(result.type, type), result.containsGenericParameters); if (result.type == null) { throw new InvalidOperationException(); } if (!result.type.IsPointer) { throw new InvalidOperationException(); } break; case DmdTypeSignatureKind.ByRef: result = Create(type.GetElementType()); result = (TryResolveType(result.type, type), result.containsGenericParameters); if (result.type == null) { throw new InvalidOperationException(); } // This currently always fails //TODO: We could func-eval MakeByRefType() if (!result.type.IsByRef) { throw new InvalidOperationException(); } break; case DmdTypeSignatureKind.TypeGenericParameter: case DmdTypeSignatureKind.MethodGenericParameter: result = (Create(type.AppDomain.System_Object).type, true); addType = false; break; case DmdTypeSignatureKind.SZArray: result = Create(type.GetElementType()); result = (TryResolveType(result.type, type), result.containsGenericParameters); if (result.type == null) { throw new InvalidOperationException(); } if (!result.type.IsArray || result.type.GetArrayRank() != 1 || !result.type.FullName.EndsWith("[]", StringComparison.Ordinal)) { throw new InvalidOperationException(); } break; case DmdTypeSignatureKind.MDArray: result = Create(type.GetElementType()); result = (TryResolveType(result.type, type), result.containsGenericParameters); if (result.type == null) { throw new InvalidOperationException(); } if (!result.type.IsArray || (result.type.GetArrayRank() == 1 && result.type.FullName.EndsWith("[]", StringComparison.Ordinal))) { throw new InvalidOperationException(); } break; case DmdTypeSignatureKind.GenericInstance: result = Create(type.GetGenericTypeDefinition()); result = (TryResolveType(result.type, type), result.containsGenericParameters); if (result.type == null) { throw new InvalidOperationException(); } // This fails on Unity (version < 2.12), since it doesn't have that info available //if (!result.type.IsGenericType) // throw new InvalidOperationException(); break; case DmdTypeSignatureKind.FunctionPointer: // It's not possible to create function pointers, so use a pointer type instead result = Create(type.AppDomain.System_Void.MakePointerType()); addType = false; break; default: throw new InvalidOperationException(); } if (result.type == null) { throw new InvalidOperationException(); } if (addType && !result.containsGenericParameters) { typeCache.Add(result.type, type); } recursionCounter--; return(result); }
public EmitType(Type type) { Type = type; TypeCache.Add(type, this); }