V18 / 8d896b8a86e5
DesktopResearchBridge.cs
Interfaces/Gui/LilithGui.Worker/DesktopResearchBridge.cs
Unchanged from the preceding versionCS
using System.Collections.Concurrent;
using System.Reflection;
using System.Text.Json;
namespace Lilith.Gui.Worker;
// Implements the selected release's interface without loading a newer Core.
public class DesktopResearchBridge : DispatchProxy, IDisposable
{
private static readonly ConcurrentDictionary<string,TaskCompletionSource<JsonElement>> Pending = new();
internal Action<string,object?>? Emit;
internal object? Options;
private static readonly JsonSerializerOptions JsonOptions = new() { PropertyNameCaseInsensitive=true };
internal static bool Complete(JsonElement payload)
{
if(!Pending.TryRemove(payload.GetProperty("requestId").GetString()!,out var completion))return false;
if(payload.TryGetProperty("error",out var error))completion.TrySetException(new IOException(error.GetString()));
else completion.TrySetResult(payload.GetProperty("result").Clone());
return true;
}
protected override object? Invoke(MethodInfo? method,object?[]? args)
{
if(method is null)throw new MissingMethodException();
if(method.Name=="Dispose"){Dispose();return null;}
var returnType=method.ReturnType.GetGenericArguments().Single();
return typeof(DesktopResearchBridge).GetMethod(nameof(Request),BindingFlags.Instance|BindingFlags.NonPublic)!
.MakeGenericMethod(returnType).Invoke(this,[method.Name,args!]);
}
private async Task<T> Request<T>(string operation,object?[] args)
{
var ct=args.OfType<CancellationToken>().FirstOrDefault();
string id=Guid.NewGuid().ToString("N");var completion=new TaskCompletionSource<JsonElement>(TaskCreationOptions.RunContinuationsAsynchronously);
Pending[id]=completion;
try
{
Emit!("browser_request",new{requestId=id,operation,value=args[0],limit=operation=="SearchAsync"?args[1]:null,options=Options});
var result=await completion.Task.WaitAsync(TimeSpan.FromMinutes(4),ct);
return result.Deserialize<T>(JsonOptions)!;
}
finally{Pending.TryRemove(id,out _);}
}
public void Dispose()=>Emit?.Invoke("browser_close",new{});
}