DotNext by Roman Sakno

<PackageReference Include="DotNext" Version="2.0.0" />

 TaskResultBinder

using System; using System.Collections.ObjectModel; using System.Linq.Expressions; using System.Reflection; using System.Runtime.CompilerServices; using System.Threading.Tasks; namespace DotNext.Runtime.CompilerServices { [System.Runtime.CompilerServices.NullableContext(1)] [System.Runtime.CompilerServices.Nullable(0)] internal sealed class TaskResultBinder : CallSiteBinder { private const string PropertyName = "Result"; private const BindingFlags PropertyFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy; private static Expression BindMissingProperty(Expression target, out Expression restrictions) { restrictions = Expression.TypeEqual(target, typeof(Task)); target = Expression.Call(target, "GetAwaiter", Type.EmptyTypes, Array.Empty<Expression>()); target = Expression.Call(target, "GetResult", Type.EmptyTypes, Array.Empty<Expression>()); return Expression.Block(typeof(object), target, Expression.Field(null, typeof(Missing), "Value")); } private static Expression BindProperty(PropertyInfo resultProperty, Expression target, out Expression restrictions) { restrictions = Expression.TypeIs(target, resultProperty.DeclaringType); target = Expression.Call(typeof(Unsafe), "As", new Type[1] { resultProperty.DeclaringType }, target); target = Expression.Property(target, resultProperty); if (!target.Type.IsValueType) return target; return Expression.Convert(target, typeof(object)); } private static Expression Bind(object targetValue, Expression target, LabelTarget returnLabel) { PropertyInfo property = targetValue.GetType().GetProperty("Result", BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy); target = (((object)property == null) ? BindMissingProperty(target, out Expression restrictions) : BindProperty(property, target, out restrictions)); target = Expression.Return(returnLabel, target); target = Expression.Condition(restrictions, target, Expression.Goto(CallSiteBinder.UpdateLabel)); return target; } public override Expression Bind(object[] args, ReadOnlyCollection<ParameterExpression> parameters, LabelTarget returnLabel) { return Bind(args[0], parameters[0], returnLabel); } } }