static DmdFieldInfo?TryGetBuilderFieldByType(DmdType type) { DmdFieldInfo?builderField = null; foreach (var field in type.Fields) { var fieldType = field.FieldType; if (fieldType.IsNested) { continue; } if (fieldType.IsConstructedGenericType) { fieldType = fieldType.GetGenericTypeDefinition(); } foreach (var info in builderWellKnownTypeNames) { if (fieldType.MetadataNamespace == info.@namespace && fieldType.MetadataName == info.name) { return(field); } } if (builderField is null && fieldType.MetadataName is not null && (fieldType.MetadataName.EndsWith("MethodBuilder", StringComparison.Ordinal) || fieldType.MetadataName.EndsWith("MethodBuilder`1", StringComparison.Ordinal))) { builderField = field; } } return(builderField); }
/// <summary> /// Gets the builder instance. It's assumed to be stored in a field in the current 'this' instance. /// /// The decompiler should already know the field. If that info isn't available, we'll try to find /// the field by name, and if that fails, by field type. /// /// null is returned if we couldn't find the field or if we failed to read the field. /// </summary> /// <param name="evalInfo">Evaluation info</param> /// <param name="builderFieldModule">Module of builder field or null if unknown</param> /// <param name="builderFieldToken">Token of builder field or 0 if unknown</param> /// <returns></returns> public static DbgDotNetValue?TryGetBuilder(DbgEvaluationInfo evalInfo, DmdModule?builderFieldModule, uint builderFieldToken) { DbgDotNetValueResult thisArg = default; DbgDotNetValueResult tmpResult = default; try { var runtime = evalInfo.Runtime.GetDotNetRuntime(); thisArg = runtime.GetParameterValue(evalInfo, 0); if (!thisArg.IsNormalResult || thisArg.Value !.IsNull) { return(null); } if (thisArg.Value.Type.IsByRef) { tmpResult = thisArg.Value.LoadIndirect(); if (!tmpResult.IsNormalResult || tmpResult.Value !.IsNull) { return(null); } thisArg.Value?.Dispose(); thisArg = tmpResult; tmpResult = default; } DmdFieldInfo?builderField = null; if (builderFieldModule is not null && builderFieldToken != 0) { builderField = thisArg.Value.Type.GetField(builderFieldModule, (int)builderFieldToken); } if (builderField is null) { builderField = TryGetBuilderField(thisArg.Value.Type); } if (builderField is null) { return(null); } Debug.Assert((object)builderField == TryGetBuilderFieldByType(thisArg.Value.Type)); Debug2.Assert(TryGetBuilderFieldByname(thisArg.Value.Type) is null || (object?)TryGetBuilderFieldByname(thisArg.Value.Type) == TryGetBuilderFieldByType(thisArg.Value.Type)); tmpResult = runtime.LoadField(evalInfo, thisArg.Value, builderField); if (!tmpResult.IsNormalResult || tmpResult.Value !.IsNull) { return(null); } var fieldValue = tmpResult.Value; tmpResult = default; return(fieldValue); } finally { thisArg.Value?.Dispose(); tmpResult.Value?.Dispose(); } }
/// <summary> /// Compares two fields /// </summary> /// <param name="a">First field</param> /// <param name="b">Second field</param> /// <returns></returns> public bool Equals(DmdFieldInfo?a, DmdFieldInfo?b) { if ((object?)a == b) { return(true); } if (a is null || b is null) { return(false); } return(MemberNameEquals(a.Name, b.Name) && Equals(a.FieldType, b.FieldType) && (!CompareDeclaringType || Equals(a.DeclaringType, b.DeclaringType))); }
/// <summary> /// Gets the hash code of a field /// </summary> /// <param name="a">Field</param> /// <returns></returns> public int GetHashCode(DmdFieldInfo?a) { if (a is null) { return(0); } int hc = MemberNameGetHashCode(a.Name); hc ^= GetHashCode(a.FieldType); if (CompareDeclaringType) { hc ^= GetHashCode(a.DeclaringType); } return(hc); }
public static (DmdFieldInfo?hasValueField, DmdFieldInfo?valueField) TryGetNullableFields(DmdType type) { Debug.Assert(type.IsNullable); DmdFieldInfo?hasValueField = null; DmdFieldInfo?valueField = null; var fields = type.DeclaredFields; for (int i = 0; i < fields.Count; i++) { var field = fields[i]; if (field.IsStatic || field.IsLiteral) { continue; } switch (field.Name) { case KnownMemberNames.Nullable_HasValue_FieldName: case KnownMemberNames.Nullable_HasValue_FieldName_Mono: if (!(hasValueField is null)) { return(null, null); } hasValueField = field; break; case KnownMemberNames.Nullable_Value_FieldName: if (!(valueField is null)) { return(null, null); } valueField = field; break; default: return(null, null); } } if (hasValueField is null || valueField is null) { return(null, null); } return(hasValueField, valueField); }
public static (DmdFieldInfo?keyField, DmdFieldInfo?valueField) TryGetFields(DmdType type, string keyFieldName, string valueFieldName) { DmdFieldInfo?keyField = null; DmdFieldInfo?valueField = null; var fields = type.DeclaredFields; for (int i = 0; i < fields.Count; i++) { var field = fields[i]; if (field.IsStatic || field.IsLiteral) { continue; } if (field.Name == keyFieldName) { if (!(keyField is null)) { return(null, null); } keyField = field; } else if (field.Name == valueFieldName) { if (!(valueField is null)) { return(null, null); } valueField = field; } else { return(null, null); } } if (keyField is null || valueField is null) { return(null, null); } return(keyField, valueField); }