using System; using System.Collections.Concurrent; using System.Linq.Expressions; using System.Threading.Tasks; namespace Blazor.Diagrams.Interop { public static class TcsUtil { private static readonly Type _tcsType = typeof(TaskCompletionSource<>); private static readonly ConcurrentDictionary> _setResults = new ConcurrentDictionary>(); private static readonly ConcurrentDictionary> _setExceptions = new ConcurrentDictionary>(); public static void SetResult(object tcs, Type resultType, object result) { var tcsSpecificType = _tcsType.MakeGenericType(resultType); var setResult = _setResults.GetOrAdd(tcsSpecificType, (tcsSpecificType) => { var tcsParamExpr = Expression.Parameter(typeof(object), "tcs"); var resultParamExpr = Expression.Parameter(typeof(object), "result"); var tcsConvertExpr = Expression.Convert(tcsParamExpr, tcsSpecificType); var resultConvertExpr = Expression.Convert(resultParamExpr, resultType); var setResultExpr = Expression.Call(tcsConvertExpr, "TrySetResult", Type.EmptyTypes, resultConvertExpr); return Expression.Lambda>(setResultExpr, tcsParamExpr, resultParamExpr).Compile(); }); setResult(tcs, result); } public static void SetException(object tcs, Type resultType, Exception exception) { var tcsSpecificType = _tcsType.MakeGenericType(resultType); var setException = _setExceptions.GetOrAdd(tcsSpecificType, (tcsSpecificType) => { var tcsParamExpr = Expression.Parameter(typeof(object), "tcs"); var exParamExpr = Expression.Parameter(typeof(Exception), "ex"); var tcsConvertExpr = Expression.Convert(tcsParamExpr, tcsSpecificType); var setResultExpr = Expression.Call(tcsConvertExpr, "TrySetException", Type.EmptyTypes, exParamExpr); return Expression.Lambda>(setResultExpr, tcsParamExpr, exParamExpr).Compile(); }); setException(tcs, exception); } } }