DotNext by .NET Foundation and Contributors

<PackageReference Include="DotNext" Version="4.0.0-beta.8" />

 TaskResultBinder

using System; using System.Collections.ObjectModel; using System.Diagnostics.CodeAnalysis; using System.Linq.Expressions; using System.Reflection; using System.Runtime.CompilerServices; using System.Threading.Tasks; namespace DotNext.Dynamic { [System.Runtime.CompilerServices.NullableContext(1)] [System.Runtime.CompilerServices.Nullable(0)] internal sealed class TaskResultBinder : CallSiteBinder { private const string ResultPropertyName = "Result"; private const BindingFlags ResultPropertyFlags = BindingFlags.Instance | BindingFlags.Public; 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)); } [DynamicDependency(DynamicallyAccessedMemberTypes.PublicProperties, typeof(Task<>))] [DynamicDependency(DynamicallyAccessedMemberTypes.PublicProperties, typeof(ValueTask<>))] private static Expression Bind(object targetValue, Expression target, LabelTarget returnLabel) { target = BindProperty(targetValue.GetType().GetProperty("Result", BindingFlags.Instance | BindingFlags.Public), target, out Expression 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); } } }