| File: CallSiteJsonFormatter.cs | Web Access |
| Project: src\runtime\src\libraries\Microsoft.Extensions.DependencyInjection\src\Microsoft.Extensions.DependencyInjection.csproj (Microsoft.Extensions.DependencyInjection) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; using System.Text; using Microsoft.Extensions.DependencyInjection.ServiceLookup; namespace Microsoft.Extensions.DependencyInjection { internal sealed class CallSiteJsonFormatter : CallSiteVisitor<CallSiteJsonFormatter.CallSiteFormatterContext, object?> { internal static readonly CallSiteJsonFormatter Instance = new CallSiteJsonFormatter(); private CallSiteJsonFormatter() { } public string Format(ServiceCallSite callSite) { var stringBuilder = new StringBuilder(); var context = new CallSiteFormatterContext(stringBuilder, 0, new HashSet<ServiceCallSite>()); VisitCallSite(callSite, context); return stringBuilder.ToString(); } protected override object? VisitConstructor(ConstructorCallSite constructorCallSite, CallSiteFormatterContext argument) { argument.WriteProperty("implementationType", constructorCallSite.ImplementationType); if (constructorCallSite.ParameterCallSites.Length > 0) { argument.StartProperty("arguments"); CallSiteFormatterContext childContext = argument.StartArray(); foreach (ServiceCallSite parameter in constructorCallSite.ParameterCallSites) { childContext.StartArrayItem(); VisitCallSite(parameter, childContext); } argument.EndArray(); } return null; } protected override object? VisitCallSiteMain(ServiceCallSite callSite, CallSiteFormatterContext argument) { if (argument.ShouldFormat(callSite)) { CallSiteFormatterContext childContext = argument.StartObject(); childContext.WriteProperty("serviceType", callSite.ServiceType); childContext.WriteProperty("kind", callSite.Kind); childContext.WriteProperty("cache", callSite.Cache.Location); base.VisitCallSiteMain(callSite, childContext); argument.EndObject(); } else { CallSiteFormatterContext childContext = argument.StartObject(); childContext.WriteProperty("ref", callSite.ServiceType); argument.EndObject(); } return null; } protected override object? VisitConstant(ConstantCallSite constantCallSite, CallSiteFormatterContext argument) { argument.WriteProperty("value", constantCallSite.DefaultValue ?? ""); return null; } protected override object? VisitServiceProvider(ServiceProviderCallSite serviceProviderCallSite, CallSiteFormatterContext argument) { return null; } protected override object? VisitIEnumerable(IEnumerableCallSite enumerableCallSite, CallSiteFormatterContext argument) { argument.WriteProperty("itemType", enumerableCallSite.ItemType); argument.WriteProperty("size", enumerableCallSite.ServiceCallSites.Length); if (enumerableCallSite.ServiceCallSites.Length > 0) { argument.StartProperty("items"); CallSiteFormatterContext childContext = argument.StartArray(); foreach (ServiceCallSite item in enumerableCallSite.ServiceCallSites) { childContext.StartArrayItem(); VisitCallSite(item, childContext); } argument.EndArray(); } return null; } protected override object? VisitFactory(FactoryCallSite factoryCallSite, CallSiteFormatterContext argument) { argument.WriteProperty("method", factoryCallSite.Factory.Method); return null; } internal struct CallSiteFormatterContext { private readonly HashSet<ServiceCallSite> _processedCallSites; public CallSiteFormatterContext(StringBuilder builder, int offset, HashSet<ServiceCallSite> processedCallSites) { Builder = builder; Offset = offset; _processedCallSites = processedCallSites; _firstItem = true; } private bool _firstItem; public int Offset { get; } public StringBuilder Builder { get; } public bool ShouldFormat(ServiceCallSite serviceCallSite) { return _processedCallSites.Add(serviceCallSite); } public CallSiteFormatterContext IncrementOffset() { return new CallSiteFormatterContext(Builder, Offset + 4, _processedCallSites) { _firstItem = true }; } public CallSiteFormatterContext StartObject() { Builder.Append('{'); return IncrementOffset(); } public void EndObject() { Builder.Append('}'); } public void StartProperty(string name) { if (!_firstItem) { Builder.Append(','); } else { _firstItem = false; } Builder.Append('"').Append(name).Append("\":"); } public void StartArrayItem() { if (!_firstItem) { Builder.Append(','); } else { _firstItem = false; } } public void WriteProperty(string name, object? value) { StartProperty(name); if (value != null) { Builder.Append(" \"").Append(value).Append('"'); } else { Builder.Append("null"); } } public CallSiteFormatterContext StartArray() { Builder.Append('['); return IncrementOffset(); } public void EndArray() { Builder.Append(']'); } } } }