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);
}
}
}