<PackageReference Include="Microsoft.CSharp" Version="4.6.0-rc1.19456.4" />

BinderHelper

static class BinderHelper
using System; using System.Collections.Generic; using System.Dynamic; using System.Linq; using System.Linq.Expressions; using System.Numerics.Hashing; using System.Reflection; using System.Runtime.InteropServices; namespace Microsoft.CSharp.RuntimeBinder { internal static class BinderHelper { private static MethodInfo s_DoubleIsNaN; private static MethodInfo s_SingleIsNaN; internal static DynamicMetaObject Bind(ICSharpBinder action, RuntimeBinder binder, DynamicMetaObject[] args, IEnumerable<CSharpArgumentInfo> arginfos, DynamicMetaObject onBindingError) { Expression[] array = new Expression[args.Length]; BindingRestrictions bindingRestrictions = BindingRestrictions.Empty; ICSharpInvokeOrInvokeMemberBinder callPayload = action as ICSharpInvokeOrInvokeMemberBinder; ParameterExpression parameterExpression = null; IEnumerator<CSharpArgumentInfo> enumerator = (arginfos ?? Array.Empty<CSharpArgumentInfo>()).GetEnumerator(); for (int i = 0; i < args.Length; i++) { DynamicMetaObject dynamicMetaObject = args[i]; CSharpArgumentInfo cSharpArgumentInfo = enumerator.MoveNext() ? enumerator.Current : null; if (i == 0 && IsIncrementOrDecrementActionOnLocal(action)) { object value = dynamicMetaObject.Value; parameterExpression = (ParameterExpression)(array[0] = Expression.Variable((value != null) ? value.GetType() : typeof(object), "t0")); } else array[i] = dynamicMetaObject.Expression; BindingRestrictions restrictions = DeduceArgumentRestriction(i, callPayload, dynamicMetaObject, cSharpArgumentInfo); bindingRestrictions = bindingRestrictions.Merge(restrictions); if (cSharpArgumentInfo != null && cSharpArgumentInfo.LiteralConstant) { if (dynamicMetaObject.Value is double && double.IsNaN((double)dynamicMetaObject.Value)) { MethodInfo method = s_DoubleIsNaN ?? (s_DoubleIsNaN = typeof(double).GetMethod("IsNaN")); Expression expression = Expression.Call(null, method, dynamicMetaObject.Expression); bindingRestrictions = bindingRestrictions.Merge(BindingRestrictions.GetExpressionRestriction(expression)); } else if (dynamicMetaObject.Value is float && float.IsNaN((float)dynamicMetaObject.Value)) { MethodInfo method2 = s_SingleIsNaN ?? (s_SingleIsNaN = typeof(float).GetMethod("IsNaN")); Expression expression2 = Expression.Call(null, method2, dynamicMetaObject.Expression); bindingRestrictions = bindingRestrictions.Merge(BindingRestrictions.GetExpressionRestriction(expression2)); } else { Expression expression3 = Expression.Equal(dynamicMetaObject.Expression, Expression.Constant(dynamicMetaObject.Value, dynamicMetaObject.Expression.Type)); restrictions = BindingRestrictions.GetExpressionRestriction(expression3); bindingRestrictions = bindingRestrictions.Merge(restrictions); } } } try { Expression expression4 = binder.Bind(action, array, args, out DynamicMetaObject deferredBinding); if (deferredBinding == null) { if (parameterExpression != null) { DynamicMetaObject dynamicMetaObject2 = args[0]; expression4 = Expression.Block(new ParameterExpression[1] { parameterExpression }, Expression.Assign(parameterExpression, Expression.Convert(dynamicMetaObject2.Expression, dynamicMetaObject2.Value.GetType())), expression4, Expression.Assign(dynamicMetaObject2.Expression, Expression.Convert(parameterExpression, dynamicMetaObject2.Expression.Type))); } expression4 = ConvertResult(expression4, action); return new DynamicMetaObject(expression4, bindingRestrictions); } expression4 = ConvertResult(deferredBinding.Expression, action); bindingRestrictions = deferredBinding.Restrictions.Merge(bindingRestrictions); return new DynamicMetaObject(expression4, bindingRestrictions); } catch (RuntimeBinderException ex) { if (onBindingError == null) return new DynamicMetaObject(Expression.Throw(Expression.New(typeof(RuntimeBinderException).GetConstructor(new Type[1] { typeof(string) }), Expression.Constant(ex.Message)), GetTypeForErrorMetaObject(action, args)), bindingRestrictions); return onBindingError; } } public static void ValidateBindArgument(DynamicMetaObject argument, string paramName) { if (argument == null) throw Error.ArgumentNull(paramName); if (!argument.HasValue) throw Error.DynamicArgumentNeedsValue(paramName); } public static void ValidateBindArgument(DynamicMetaObject[] arguments, string paramName) { if (arguments != null) { for (int i = 0; i != arguments.Length; i++) { ValidateBindArgument(arguments[i], $"{paramName}""{i}"""); } } } private static bool IsTypeOfStaticCall(int parameterIndex, ICSharpInvokeOrInvokeMemberBinder callPayload) { if (parameterIndex == 0 && callPayload != null) return callPayload.StaticCall; return false; } private static bool IsComObject(object obj) { if (obj != null) return Marshal.IsComObject(obj); return false; } private static bool IsTransparentProxy(object obj) { return false; } private static bool IsDynamicallyTypedRuntimeProxy(DynamicMetaObject argument, CSharpArgumentInfo info) { return info != null && !info.UseCompileTimeType && (IsComObject(argument.Value) || IsTransparentProxy(argument.Value)); } private static BindingRestrictions DeduceArgumentRestriction(int parameterIndex, ICSharpInvokeOrInvokeMemberBinder callPayload, DynamicMetaObject argument, CSharpArgumentInfo info) { if (argument.Value != null && !IsTypeOfStaticCall(parameterIndex, callPayload) && !IsDynamicallyTypedRuntimeProxy(argument, info)) return BindingRestrictions.GetTypeRestriction(argument.Expression, argument.RuntimeType); return BindingRestrictions.GetInstanceRestriction(argument.Expression, argument.Value); } private static Expression ConvertResult(Expression binding, ICSharpBinder action) { if (action is CSharpInvokeConstructorBinder) return binding; if (binding.Type == typeof(void)) { ICSharpInvokeOrInvokeMemberBinder iCSharpInvokeOrInvokeMemberBinder = action as ICSharpInvokeOrInvokeMemberBinder; if (iCSharpInvokeOrInvokeMemberBinder != null && iCSharpInvokeOrInvokeMemberBinder.ResultDiscarded) return Expression.Block(binding, Expression.Default(action.ReturnType)); throw Error.BindToVoidMethodButExpectResult(); } if (binding.Type.IsValueType && !action.ReturnType.IsValueType) return Expression.Convert(binding, action.ReturnType); return binding; } private static Type GetTypeForErrorMetaObject(ICSharpBinder action, DynamicMetaObject[] args) { if (action is CSharpInvokeConstructorBinder) return args[0].Value as Type; return action.ReturnType; } private static bool IsIncrementOrDecrementActionOnLocal(ICSharpBinder action) { CSharpUnaryOperationBinder cSharpUnaryOperationBinder = action as CSharpUnaryOperationBinder; if (cSharpUnaryOperationBinder != null) { if (cSharpUnaryOperationBinder.Operation != ExpressionType.Increment) return cSharpUnaryOperationBinder.Operation == ExpressionType.Decrement; return true; } return false; } internal static T[] Cons<T>(T sourceHead, T[] sourceTail) { if (sourceTail == null || sourceTail.Length != 0) { T[] array = new T[sourceTail.Length + 1]; array[0] = sourceHead; sourceTail.CopyTo(array, 1); return array; } return new T[1] { sourceHead }; } internal static T[] Cons<T>(T sourceHead, T[] sourceMiddle, T sourceLast) { if (sourceMiddle == null || sourceMiddle.Length != 0) { T[] array = new T[sourceMiddle.Length + 2]; array[0] = sourceHead; array[array.Length - 1] = sourceLast; sourceMiddle.CopyTo(array, 1); return array; } return new T[2] { sourceHead, sourceLast }; } internal static T[] ToArray<T>(IEnumerable<T> source) { if (source != null) return source.ToArray(); return Array.Empty<T>(); } internal static CallInfo CreateCallInfo(ref IEnumerable<CSharpArgumentInfo> argInfos, int discard) { int num = 0; List<string> list = new List<string>(); CSharpArgumentInfo[] array = (CSharpArgumentInfo[])(argInfos = ToArray(argInfos)); foreach (CSharpArgumentInfo cSharpArgumentInfo in array) { if (cSharpArgumentInfo.NamedArgument) list.Add(cSharpArgumentInfo.Name); num++; } return new CallInfo(num - discard, list); } internal static string GetCLROperatorName(this ExpressionType p) { switch (p) { default: return null; case ExpressionType.Add: return "op_Addition"; case ExpressionType.Subtract: return "op_Subtraction"; case ExpressionType.Multiply: return "op_Multiply"; case ExpressionType.Divide: return "op_Division"; case ExpressionType.Modulo: return "op_Modulus"; case ExpressionType.LeftShift: return "op_LeftShift"; case ExpressionType.RightShift: return "op_RightShift"; case ExpressionType.LessThan: return "op_LessThan"; case ExpressionType.GreaterThan: return "op_GreaterThan"; case ExpressionType.LessThanOrEqual: return "op_LessThanOrEqual"; case ExpressionType.GreaterThanOrEqual: return "op_GreaterThanOrEqual"; case ExpressionType.Equal: return "op_Equality"; case ExpressionType.NotEqual: return "op_Inequality"; case ExpressionType.And: return "op_BitwiseAnd"; case ExpressionType.ExclusiveOr: return "op_ExclusiveOr"; case ExpressionType.Or: return "op_BitwiseOr"; case ExpressionType.AddAssign: return "op_Addition"; case ExpressionType.SubtractAssign: return "op_Subtraction"; case ExpressionType.MultiplyAssign: return "op_Multiply"; case ExpressionType.DivideAssign: return "op_Division"; case ExpressionType.ModuloAssign: return "op_Modulus"; case ExpressionType.AndAssign: return "op_BitwiseAnd"; case ExpressionType.ExclusiveOrAssign: return "op_ExclusiveOr"; case ExpressionType.OrAssign: return "op_BitwiseOr"; case ExpressionType.LeftShiftAssign: return "op_LeftShift"; case ExpressionType.RightShiftAssign: return "op_RightShift"; case ExpressionType.Negate: return "op_UnaryNegation"; case ExpressionType.UnaryPlus: return "op_UnaryPlus"; case ExpressionType.Not: return "op_LogicalNot"; case ExpressionType.OnesComplement: return "op_OnesComplement"; case ExpressionType.IsTrue: return "op_True"; case ExpressionType.IsFalse: return "op_False"; case ExpressionType.Increment: return "op_Increment"; case ExpressionType.Decrement: return "op_Decrement"; } } internal static int AddArgHashes(int hash, Type[] typeArguments, CSharpArgumentInfo[] argInfos) { foreach (Type type in typeArguments) { hash = HashHelpers.Combine(hash, type.GetHashCode()); } return AddArgHashes(hash, argInfos); } internal static int AddArgHashes(int hash, CSharpArgumentInfo[] argInfos) { foreach (CSharpArgumentInfo cSharpArgumentInfo in argInfos) { hash = HashHelpers.Combine(hash, (int)cSharpArgumentInfo.Flags); string name = cSharpArgumentInfo.Name; if (!string.IsNullOrEmpty(name)) hash = HashHelpers.Combine(hash, name.GetHashCode()); } return hash; } internal static bool CompareArgInfos(Type[] typeArgs, Type[] otherTypeArgs, CSharpArgumentInfo[] argInfos, CSharpArgumentInfo[] otherArgInfos) { for (int i = 0; i < typeArgs.Length; i++) { if (typeArgs[i] != otherTypeArgs[i]) return false; } return CompareArgInfos(argInfos, otherArgInfos); } internal static bool CompareArgInfos(CSharpArgumentInfo[] argInfos, CSharpArgumentInfo[] otherArgInfos) { for (int i = 0; i < argInfos.Length; i++) { CSharpArgumentInfo cSharpArgumentInfo = argInfos[i]; CSharpArgumentInfo cSharpArgumentInfo2 = otherArgInfos[i]; if (cSharpArgumentInfo.Flags != cSharpArgumentInfo2.Flags || cSharpArgumentInfo.Name != cSharpArgumentInfo2.Name) return false; } return true; } } }