in libraries/Microsoft.Bot.Builder.Dialogs.Declarative/Converters/InterfaceConverter.cs [66:159]
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var (jToken, range) = SourceScope.ReadTokenRange(reader, sourceContext);
using (new SourceScope(sourceContext, range))
{
string refDialogName = null;
if (resourceExplorer.IsRef(jToken))
{
refDialogName = jToken.Value<string>();
// We can't do this asynchronously as the Json.NET interface is synchronous
var reference = resourceExplorer.ResolveRefInternalAsync(jToken, sourceContext).GetAwaiter().GetResult();
jToken = reference.token;
if (!rangeReferences.ContainsKey(jToken))
{
rangeReferences.Add(jToken, reference.range);
}
}
var kind = (string)jToken["$kind"];
if (kind == null)
{
// see if there is jObject resolver
var unKnownResult = ResolveUnknownObject(jToken);
if (unKnownResult != null)
{
return unKnownResult;
}
throw new ArgumentNullException($"$kind was not found: {JsonConvert.SerializeObject(jToken)}");
}
// if reference resolution made a source context available for the JToken, then add it to the context stack
var found = rangeReferences.TryGetValue(jToken, out var rangeResolved);
using (var newScope = found ? new SourceScope(sourceContext, rangeResolved) : null)
{
var passTwo = false;
foreach (var observer in this.observers)
{
if (observer is CycleDetectionObserver cycDetectObserver && cycDetectObserver.CycleDetectionPass == CycleDetectionPasses.PassTwo)
{
passTwo = true;
}
if (observer.OnBeforeLoadToken(sourceContext, rangeResolved ?? range, jToken, out T interceptResult))
{
return interceptResult;
}
}
var tokenToBuild = TryAssignId(jToken, sourceContext);
T result;
if (passTwo && refDialogName != null && cachedRefDialogs.ContainsKey(refDialogName))
{
result = cachedRefDialogs[refDialogName];
}
else
{
result = BuildOrGetType(kind, tokenToBuild, serializer, passTwo, (rangeResolved ?? range).ToString());
if (passTwo && refDialogName != null)
{
cachedRefDialogs[refDialogName] = result;
resourceExplorer.UpdateResourceTokenCache(refDialogName, tokenToBuild, range);
}
}
// Associate the most specific source context information with this item
if (sourceContext.CallStack.Count > 0)
{
range = sourceContext.CallStack.Peek().DeepClone();
if (!DebugSupport.SourceMap.TryGetValue(result, out var _))
{
DebugSupport.SourceMap.Add(result, range);
}
}
foreach (var observer in this.observers)
{
if (observer.OnAfterLoadToken(sourceContext, range, jToken, result, out T interceptedResult))
{
return interceptedResult;
}
}
return result;
}
}
}