TaskResultBinder
using System;
using System.Collections.ObjectModel;
using System.Diagnostics.CodeAnalysis;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.CompilerServices;
namespace DotNext.Dynamic
{
[RequiresDynamicCode("DLR is required to resolve underlying task type at runtime")]
[RequiresUnreferencedCode("Dynamic code generation may be incompatible with IL trimming")]
internal sealed class TaskResultBinder : CallSiteBinder
{
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)
{
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);
}
}
}