public static string DiagName(this ICall call, DiagContextInternal ctx) { var substituteId = call.Target().SubstituteId(ctx); var callArgs = call.FormatArgs(ctx); var signature = call.GetMethodInfo().DiagName(); return($"<[{substituteId}].{callArgs} Signature: {signature}>"); }
public static string DiagName(this ICallRouter callRouter, DiagContextInternal ctx) { var name = $"<{callRouter.GetObjectId(ctx)}"; if (ctx.TryGetSubstituteForRouter(callRouter, out object substitute)) { name += $"#{substitute.SubstituteId(ctx)}"; } return($"{name}>"); }
public static string SubstituteId(this object substitute, DiagContextInternal ctx) { string proxyType = ""; if (ctx.TryGetSubstitutePrimaryType(substitute, out Type primaryType)) { proxyType = $".{primaryType.DiagName()}"; } return($"Substitute{proxyType}|{RuntimeHelpers.GetHashCode(substitute):x8}"); }
public static string GetObjectId(this object obj, DiagContextInternal ctx) { if (obj is null) { return("<null>"); } if (obj is ICallRouterProvider) { return(obj.SubstituteId(ctx)); } var type = obj.GetType(); var typeName = type.GetNonMangledTypeName(); // Trim "Diagnostics" prefix from type to make output more clear. // It doesn't matter to end user whether we have wrapper - we don't alter the logic. if (type.Assembly == Assembly.GetExecutingAssembly() && typeName.StartsWith("Diagnostics", StringComparison.Ordinal)) { typeName = typeName.Substring("Diagnostics".Length); } string id; if (type == typeof(string)) { id = $"\"{obj}\""; } else if (type.IsEnum) { id = $"<{obj}>"; } else if (type.IsPrimitive) { id = obj.ToString(); } else if (obj is ICallRouter || obj is IPendingSpecification || obj is IProxyFactory || obj is IThreadLocalContext) { id = obj.GetHashCode().ToString("x8"); } // It's unsafe to call `.ToString()` on unknown types, as this method might be overridden and it will // lead to a substitute member invocation. In rare cases it might lead to the stack overflow. // To mitigate that we invoke method which doesn't invoke custom client code. else { id = RuntimeHelpers.GetHashCode(obj).ToString("x8"); } return($"{typeName}|{id}"); }
public static string DiagName(this IReturn value, DiagContextInternal ctx) { var unknown = $"<UNKNOWN|{value.GetType().DiagName()}>"; if (value is ReturnValue rvs) { return(ReflectionReader.ReadFieldValue( rvs, "_value", (object o) => o.GetObjectId(ctx), "<VALUE|CANNOT_READ>")); } var valueType = value.GetType(); if (!valueType.IsGenericType) { return(unknown); } var gtd = valueType.GetGenericTypeDefinition(); if (gtd == typeof(ReturnMultipleValues <>)) { return(ReflectionReader.ReadFieldValue( value, "_valuesToReturn", (IEnumerable objs) => objs.Cast <object>().Print(o => o.GetObjectId(ctx)), "<MVALUES|CANNOT_READ>")); } if (gtd == typeof(ReturnValueFromFunc <>)) { return(ReflectionReader.ReadFieldValue( value, "_funcToReturnValue", (Delegate d) => $"<FUNC|{d.DiagName()}>", "<FVALUE|CANNOT_READ>")); } if (gtd == typeof(ReturnMultipleFuncsValues <>)) { return(ReflectionReader.ReadFieldValue( value, "_funcsToReturn", (IEnumerable <Delegate> ds) => $"<FUNCS|{ds.Print(DiagName)}>", "<FMVALUES|CANNOT_READ>")); } return(unknown); }
public DiagnosticsThreadLocalContext(IThreadLocalContext impl, DiagContextInternal ctx) { _impl = impl; _ctx = ctx; PendingSpecification = new DiagnosticsPendingSpecification(impl.PendingSpecification, ctx); }
public DiagnosticsProxyFactory(IProxyFactory impl, DiagContextInternal ctx) { _impl = impl; _ctx = ctx; }
public DiagnosticsCallRouter(ICallRouter impl, DiagContextInternal ctx) { _impl = impl; _ctx = ctx; }
public static string DiagName(this PendingSpecificationInfo pendingSpecification, DiagContextInternal ctx) { string innerInfo = pendingSpecification.Handle( spec => $"SPEC|{spec.DiagName()}", call => $"CALL|{call.DiagName(ctx)}"); return($"<{innerInfo}>"); }
public static string FormatArgs(this ICall call, DiagContextInternal ctx) { var methodInfo = call.GetMethodInfo(); return(CallFormatter.Format(methodInfo, call.GetOriginalArguments().Select(a => a.GetObjectId(ctx)))); }
public DiagnosticsPendingSpecification(IPendingSpecification impl, DiagContextInternal ctx) { _impl = impl; _ctx = ctx; }