/// <summary>
/// Creates a <see cref="DynamicExpression" /> that represents a dynamic operation bound by the provided <see cref="CallSiteBinder" />.
/// </summary>
/// <param name="binder">The runtime binder for the dynamic operation.</param>
/// <param name="returnType">The result type of the dynamic expression.</param>
/// <param name="arg0">The first argument to the dynamic operation.</param>
/// <param name="arg1">The second argument to the dynamic operation.</param>
/// <param name="arg2">The third argument to the dynamic operation.</param>
/// <returns>
/// A <see cref="DynamicExpression" /> that has <see cref="NodeType" /> equal to
/// <see cref="ExpressionType.Dynamic">Dynamic</see> and has the
/// <see cref="DynamicExpression.Binder">Binder</see> and
/// <see cref="DynamicExpression.Arguments">Arguments</see> set to the specified values.
/// </returns>
/// <remarks>
/// The <see cref="DynamicExpression.DelegateType">DelegateType</see> property of the
/// result will be inferred from the types of the arguments and the specified return type.
/// </remarks>
public static DynamicExpression Dynamic(CallSiteBinder binder, Type returnType, Expression arg0, Expression arg1, Expression arg2)
{
ContractUtils.RequiresNotNull(binder, nameof(binder));
ValidateDynamicArgument(arg0, nameof(arg0));
ValidateDynamicArgument(arg1, nameof(arg1));
ValidateDynamicArgument(arg2, nameof(arg2));
DelegateHelpers.TypeInfo info = DelegateHelpers.GetNextTypeInfo(
returnType,
DelegateHelpers.GetNextTypeInfo(
arg2.Type,
DelegateHelpers.GetNextTypeInfo(
arg1.Type,
DelegateHelpers.GetNextTypeInfo(
arg0.Type,
DelegateHelpers.NextTypeInfo(typeof(CallSite))
)
)
)
);
Type delegateType = info.DelegateType;
if (delegateType == null)
{
delegateType = info.MakeDelegateType(returnType, arg0, arg1, arg2);
}
return(DynamicExpression.Make(returnType, delegateType, binder, arg0, arg1, arg2));
}