/// <summary> /// Returns an enumerable debug view. These types are located in System.Core / System.Linq. If <paramref name="enumerableType"/> /// is <see cref="System.Collections.IEnumerable"/>, then <c>System.Linq.SystemCore_EnumerableDebugView</c>'s constructor /// is returned, else if <paramref name="enumerableType"/> is <see cref="IEnumerable{T}"/>, then /// <c>System.Linq.SystemCore_EnumerableDebugView`1</c>'s constructor is returned. /// </summary> /// <param name="enumerableType">Enumerable type, must be one of <see cref="System.Collections.IEnumerable"/>, <see cref="IEnumerable{T}"/></param> /// <returns></returns> public static DmdConstructorInfo GetEnumerableDebugViewConstructor(DmdType enumerableType) { Debug.Assert(enumerableType == enumerableType.AppDomain.System_Collections_IEnumerable || (enumerableType.IsConstructedGenericType && enumerableType.GetGenericTypeDefinition() == enumerableType.AppDomain.System_Collections_Generic_IEnumerable_T)); var appDomain = enumerableType.AppDomain; var wellKnownType = enumerableType.IsConstructedGenericType ? DmdWellKnownType.System_Linq_SystemCore_EnumerableDebugView_T : DmdWellKnownType.System_Linq_SystemCore_EnumerableDebugView; var debugViewType = appDomain.GetWellKnownType(wellKnownType, isOptional: true); // If this fails, System.Core (.NET Framework) / System.Linq (.NET Core) hasn't been loaded yet if ((object)debugViewType == null) { return(null); } if (enumerableType.IsConstructedGenericType) { var genericArgs = enumerableType.GetGenericArguments(); if (debugViewType.GetGenericArguments().Count != genericArgs.Count) { return(null); } debugViewType = debugViewType.MakeGenericType(genericArgs); } var ctor = debugViewType.GetConstructor(DmdBindingFlags.Public | DmdBindingFlags.NonPublic | DmdBindingFlags.Instance, DmdCallingConventions.Standard | DmdCallingConventions.HasThis, new[] { enumerableType }); Debug.Assert((object)ctor != null); return(ctor); }
public static bool IsKeyValuePair(DmdType type) { if (!type.IsConstructedGenericType) { return(false); } type = type.GetGenericTypeDefinition(); return(type == type.AppDomain.GetWellKnownType(DmdWellKnownType.System_Collections_Generic_KeyValuePair_T2)); }
public void Add(DmdType type) { if (recursionCounter > 100) { return; } recursionCounter++; while (type.GetElementType() is DmdType etype) { type = etype; } switch (type.TypeSignatureKind) { case DmdTypeSignatureKind.Type: modules.Add(type.Module); break; case DmdTypeSignatureKind.Pointer: case DmdTypeSignatureKind.ByRef: case DmdTypeSignatureKind.TypeGenericParameter: case DmdTypeSignatureKind.MethodGenericParameter: case DmdTypeSignatureKind.SZArray: case DmdTypeSignatureKind.MDArray: break; case DmdTypeSignatureKind.GenericInstance: modules.Add(type.GetGenericTypeDefinition().Module); foreach (var ga in type.GetGenericArguments()) { Add(ga); } break; case DmdTypeSignatureKind.FunctionPointer: var sig = type.GetFunctionPointerMethodSignature(); Add(sig.ReturnType); foreach (var t in sig.GetParameterTypes()) { Add(t); } foreach (var t in sig.GetVarArgsParameterTypes()) { Add(t); } break; default: Debug.Fail($"Unknown kind: {type.TypeSignatureKind}"); break; } recursionCounter--; }
public static bool IsKeyValuePair(DmdType type) { if (type.MetadataName != "KeyValuePair`2" || type.MetadataNamespace != "System.Collections.Generic") { return(false); } if (!type.IsConstructedGenericType) { return(false); } type = type.GetGenericTypeDefinition(); return(type == type.AppDomain.GetWellKnownType(DmdWellKnownType.System_Collections_Generic_KeyValuePair_T2, isOptional: true)); }
public static (DmdConstructorInfo ctor, DmdMethodInfo toArrayMethod) GetListEnumerableMethods(DmdType objType, DmdType enumerableType) { Debug.Assert(enumerableType == enumerableType.AppDomain.System_Collections_IEnumerable || (enumerableType.IsConstructedGenericType && enumerableType.GetGenericTypeDefinition() == enumerableType.AppDomain.System_Collections_Generic_IEnumerable_T)); var appDomain = enumerableType.AppDomain; if (enumerableType.IsConstructedGenericType) { var genArgs = enumerableType.GetGenericArguments(); Debug.Assert(genArgs.Count == 1); if (genArgs.Count != 1) { return(default);
static EnumerableTypeKind GetEnumerableTypeKind(DmdType type, DmdType enumerableType, DmdType enumerableOfTType) { if (type == enumerableType) { return(EnumerableTypeKind.Enumerable); } if (type.IsConstructedGenericType && type.GetGenericArguments().Count == 1) { if (type.GetGenericTypeDefinition() == enumerableOfTType) { return(EnumerableTypeKind.EnumerableOfT); } } return(EnumerableTypeKind.None); }
static bool ShouldIgnoreDebuggerDisplayAttribute(DmdType type) { // We have special support for formatting KeyValuePair<K, V> and DictionaryEntry, so ignore all DebuggerDisplayAttributes. // (Only Unity and older Mono versions have a DebuggerDisplayAttribute on them) if (type.IsConstructedGenericType) { if (type.MetadataName == "KeyValuePair`2" && type.MetadataNamespace == "System.Collections.Generic") { return(type.GetGenericTypeDefinition() == type.AppDomain.GetWellKnownType(DmdWellKnownType.System_Collections_Generic_KeyValuePair_T2, isOptional: true)); } return(false); } else { if (type.MetadataName == "DictionaryEntry" && type.MetadataNamespace == "System.Collections") { return(type == type.AppDomain.GetWellKnownType(DmdWellKnownType.System_Collections_DictionaryEntry, isOptional: true)); } return(false); } }
TypeMirror TryResolveType(TypeMirror monoType, DmdType realType) { var fullName = realType.FullName; if (fullName == null && realType.IsGenericType) { fullName = realType.GetGenericTypeDefinition().FullName; } if (string.IsNullOrEmpty(fullName)) { return(null); } // This fails if fullName is a generic instantiated type and at least one generic argument // is a type in another assembly, eg. List<MyType>. var result = monoType.Module.Assembly.GetType(fullName); if (result != null) { return(result); } return(monoTypeLoader?.Load(monoType.Assembly, fullName)); }
(DisplayPart[] nameParts, DisplayPart[] valueParts, DisplayPart[] typeParts) GetDisplayParts(DmdType type) { var ddaType = type.AppDomain.GetWellKnownType(DmdWellKnownType.System_Diagnostics_DebuggerDisplayAttribute, isOptional: true); Debug.Assert((object)ddaType != null); // We have special support for formatting KeyValuePair<K, V>, so ignore all DebuggerDisplayAttributes. // (Only Unity and older Mono versions have a DebuggerDisplayAttribute on it) bool forceNoAttr = type.IsConstructedGenericType && type.GetGenericTypeDefinition() == type.AppDomain.GetWellKnownType(DmdWellKnownType.System_Collections_Generic_KeyValuePair_T2, isOptional: true); string nameDisplayString = null, valueDisplayString = null, typeDisplayString = null; if (!forceNoAttr && (object)ddaType != null) { var attr = type.FindCustomAttribute(ddaType, inherit: true); if (attr == null) { if (type.CanCastTo(type.AppDomain.System_Type)) { // Show the same thing VS shows valueDisplayString = @"\{Name = {Name} FullName = {FullName}\}"; } } else { if (attr.ConstructorArguments.Count == 1) { valueDisplayString = attr.ConstructorArguments[0].Value as string; } nameDisplayString = GetString(attr, nameof(DebuggerDisplayAttribute.Name)); typeDisplayString = GetString(attr, nameof(DebuggerDisplayAttribute.Type)); } } var nameParts = CreateDisplayParts(nameDisplayString); var valueParts = CreateDisplayParts(valueDisplayString); var typeParts = CreateDisplayParts(typeDisplayString); return(nameParts, valueParts, typeParts); }
public CorType Create(DmdType type) { if ((object)type == null) { throw new ArgumentNullException(nameof(type)); } if (recursionCounter++ > 100) { throw new InvalidOperationException(); } CorType result; int i; ReadOnlyCollection <DmdType> types; CorType[] corTypes; DnModule dnModule; switch (type.TypeSignatureKind) { case DmdTypeSignatureKind.Type: if (!engine.TryGetDnModule(type.Module.GetDebuggerModule() ?? throw new InvalidOperationException(), out dnModule)) { throw new InvalidOperationException(); } Debug.Assert((type.MetadataToken >> 24) == 0x02); result = dnModule.CorModule.GetClassFromToken((uint)type.MetadataToken).GetParameterizedType(type.IsValueType ? CorElementType.ValueType : CorElementType.Class); break; case DmdTypeSignatureKind.Pointer: result = Create(type.GetElementType()); result = appDomain.GetPtr(result); break; case DmdTypeSignatureKind.ByRef: result = Create(type.GetElementType()); result = appDomain.GetByRef(result); break; case DmdTypeSignatureKind.TypeGenericParameter: case DmdTypeSignatureKind.MethodGenericParameter: throw new InvalidOperationException(); case DmdTypeSignatureKind.SZArray: result = Create(type.GetElementType()); result = appDomain.GetSZArray(result); break; case DmdTypeSignatureKind.MDArray: result = Create(type.GetElementType()); result = appDomain.GetArray(result, (uint)type.GetArrayRank()); break; case DmdTypeSignatureKind.GenericInstance: result = Create(type.GetGenericTypeDefinition()); types = type.GetGenericArguments(); corTypes = new CorType[types.Count]; for (i = 0; i < corTypes.Length; i++) { corTypes[i] = Create(types[i]); } result = result.Class.GetParameterizedType(type.IsValueType ? CorElementType.ValueType : CorElementType.Class, corTypes); break; case DmdTypeSignatureKind.FunctionPointer: var methodSig = type.GetFunctionPointerMethodSignature(); types = methodSig.GetParameterTypes(); corTypes = new CorType[1 + types.Count + methodSig.GetVarArgsParameterTypes().Count]; corTypes[0] = Create(methodSig.ReturnType); for (i = 0; i < types.Count; i++) { corTypes[i + 1] = Create(types[i]); } types = methodSig.GetVarArgsParameterTypes(); for (i = 0; i < types.Count; i++) { corTypes[i + 1 + methodSig.GetParameterTypes().Count] = Create(types[i]); } result = appDomain.GetFnPtr(corTypes); break; default: throw new InvalidOperationException(); } if (result == null) { throw new InvalidOperationException(); } recursionCounter--; return(result); }
(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); }