public override DynamicMetaObject FallbackGetMember(DynamicMetaObject target, DynamicMetaObject?errorSuggestion) { // First try COM binding. if (ComBinder.TryBindGetMember(this, target, out var result, true)) { return(result); } // Defer if any object has no value so that we evaluate their Expressions and nest a // CallSite for the InvokeMember. if (!target.HasValue) { return(Defer(target)); } // Find our own binding. var members = target.LimitType.GetMember(Name, BindingFlags.IgnoreCase | BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public); return(members.Length == 1 ? new DynamicMetaObject( RuntimeHelpers.EnsureObjectResult(Expression.MakeMemberAccess( Expression.Convert(target.Expression, members[0].DeclaringType !), members[0])), // Don't need restriction test for name since this rule is only used where binder // is used, which is only used in sites with this binder.Name. BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType)) : errorSuggestion ?? RuntimeHelpers.CreateThrow(target, null, BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType), typeof(MissingMemberException), $"cannot bind member, {Name}, on object {target.Value}")); }
public override DynamicMetaObject FallbackSetMember(DynamicMetaObject target, DynamicMetaObject value, DynamicMetaObject errorSuggestion) { if (ComBinder.TryBindSetMember(this, target, value, out DynamicMetaObject result)) { return(result); } if (!target.HasValue) { return(Defer(target)); } var flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.Static; var members = target.LimitType.GetMember(Name, flags); if (members.Length == 1) { var member = members[0]; Expression val; switch (member.MemberType) { case MemberTypes.Property: val = Expression.Convert(value.Expression, ((PropertyInfo)member).PropertyType); break; case MemberTypes.Field: val = Expression.Convert(value.Expression, ((FieldInfo)member).FieldType); break; default: { var error = new string[] { "Only property and field setting is supported!" }; return(errorSuggestion ?? RuntimeHelpers.CreateThrow(target, null, BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType), typeof(InvalidOperationException), error)); } } return(new DynamicMetaObject( RuntimeHelpers.EnsureObjectResult( Expression.Assign( Expression.MakeMemberAccess( Expression.Convert(target.Expression, members[0].DeclaringType), members[0]), val)), BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType))); } else { var error = new string[] { $"\"{target.RuntimeType}\" contains {members.Length} definitions of \"{Name}\"!" }; return(errorSuggestion ?? RuntimeHelpers.CreateThrow(target, null, BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType), typeof(MissingMemberException), error)); } }
/// <summary> /// Gets a <see cref="ComObject"/> that wraps the runtime-callable-wrapper, or creates one if none currently exists. /// </summary> /// <returns></returns> public static ComObject ObjectToComObject(object rcw) { Debug.Assert(ComBinder.IsComObject(rcw)); object data = Marshal.GetComObjectData(rcw, s_comObjectInfoKey); if (data != null) { return((ComObject)data); } lock (s_comObjectInfoKey) { data = Marshal.GetComObjectData(rcw, s_comObjectInfoKey); if (data != null) { return((ComObject)data); } ComObject comObjectInfo = CreateComObject(rcw); if (!Marshal.SetComObjectData(rcw, s_comObjectInfoKey, comObjectInfo)) { throw Error.SetComObjectDataFailed(); } return(comObjectInfo); } }
public override DynamicMetaObject FallbackInvokeMember(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject?errorSuggestion) { // First try COM binding. if (ComBinder.TryBindInvokeMember(this, target, args, out var result)) { return(result); } // Defer if any object has no value so that we evaluate their Expressions and nest a // CallSite for the InvokeMember. if (!target.HasValue || Array.Exists(args, a => !a.HasValue)) { var deferArgs = new DynamicMetaObject[args.Length + 1]; deferArgs[0] = target; args.CopyTo(deferArgs.AsSpan(1)); return(Defer(deferArgs)); } // Find our own binding. Could consider allowing invoking static members from an instance. var members = target.LimitType.GetMember(Name, BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public); if (members.Length == 1 && (members[0] is PropertyInfo || members[0] is FieldInfo)) { // NEED TO TEST, should check for delegate value too // var mem = members[0]; throw new NotImplementedException(); //return new DynamicMetaObject( // Expression.Dynamic( // new SymplInvokeBinder(new CallInfo(args.Length)), // typeof(object), // args.Select(a => a.Expression).AddFirst( // Expression.MakeMemberAccess(this.Expression, mem))); // Don't test for eventinfos since we do nothing with them now. } else { // Get MethodInfos with param types that work for args. This works except for value // args that need to pass to reftype params. We could detect that to be smarter and // then explicitly StrongBox the args. var res = Array.FindAll(members, meth => meth is MethodInfo m && m.GetParameters().Length == args.Length && RuntimeHelpers.ParametersMatchArguments(m.GetParameters(), args)); // False below means generate a type restriction on the MO. We are looking at the // members targetMO's Type. var restrictions = RuntimeHelpers.GetTargetArgsRestrictions(target, args, false); if (res.Length == 0) { return(errorSuggestion ?? RuntimeHelpers.CreateThrow(target, args, restrictions, typeof(MissingMemberException), $"Can't bind member invoke -- {args}")); } // restrictions and conversion must be done consistently. var callArgs = RuntimeHelpers.ConvertArguments(args, ((MethodInfo)res[0]).GetParameters()); return(new DynamicMetaObject(RuntimeHelpers.EnsureObjectResult(Expression.Call(Expression.Convert(target.Expression, target.LimitType), (MethodInfo)res[0], callArgs)), restrictions)); // Could hve tried just letting expression.Call factory do the work, but if there is more // than one applicable method using just assignablefrom, expression.Call throws. It does // not pick a "most applicable" method or any method. } }
public override DynamicMetaObject FallbackSetMember(DynamicMetaObject target, DynamicMetaObject value, DynamicMetaObject?errorSuggestion) { // First try COM binding. if (ComBinder.TryBindSetMember(this, target, value, out var result)) { return(result); } // Defer if any object has no value so that we evaluate their Expressions and nest a // CallSite for the InvokeMember. if (!target.HasValue) { return(Defer(target)); } // Find our own binding. var members = target.LimitType.GetMember(Name, BindingFlags.IgnoreCase | BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public); if (members.Length == 1) { var mem = members[0]; Expression val; switch (mem.MemberType) { // Should check for member domain type being Type and value being TypeModel, similar // to ConvertArguments, and building an expression like GetRuntimeTypeMoFromModel. case MemberTypes.Property: val = Expression.Convert(value.Expression, ((PropertyInfo)mem).PropertyType); break; case MemberTypes.Field: val = Expression.Convert(value.Expression, ((FieldInfo)mem).FieldType); break; default: return(errorSuggestion ?? RuntimeHelpers.CreateThrow(target, null, BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType), typeof(InvalidOperationException), "Sympl only supports setting Properties and fields at this time.")); } return(new DynamicMetaObject( // Assign returns the stored value, so we're good for Sympl. RuntimeHelpers.EnsureObjectResult(Expression.Assign( Expression.MakeMemberAccess(Expression.Convert(target.Expression, members[0].DeclaringType !), members[0]), val)), // Don't need restriction test for name since this rule is only used where binder // is used, which is only used in sites with this binder.Name. BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType))); } else { return(errorSuggestion ?? RuntimeHelpers.CreateThrow(target, null, BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType), typeof(MissingMemberException), "IDynObj member name conflict.")); } }
public override DynamicMetaObject FallbackInvoke( DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion) { DynamicMetaObject result; if (ComBinder.TryBindInvoke(this, target, args, out result)) { return(result); } // Defer if any object has no value so that we evaulate their // Expressions and nest a CallSite for the InvokeMember. if (!target.HasValue || args.Any((a) => !a.HasValue)) { var deferArgs = new DynamicMetaObject[args.Length + 1]; for (int i = 0; i < args.Length; i++) { deferArgs[i + 1] = args[i]; } deferArgs[0] = target; return(Defer(deferArgs)); } if (target.LimitType.IsSubclassOf(typeof(Delegate))) { var parms = target.LimitType.GetMethod("Invoke").GetParameters(); if (parms.Length == args.Length) { // Don't need to check if argument types match parameters. // If they don't, users get an argument conversion error. var callArgs = RuntimeHelpers.ConvertArguments(args, parms); var expression = Expression.Invoke( Expression.Convert(target.Expression, target.LimitType), callArgs); return(new DynamicMetaObject( RuntimeHelpers.EnsureObjectResult(expression), BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType))); } } return(errorSuggestion ?? RuntimeHelpers.CreateThrow( target, args, BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType), typeof(InvalidOperationException), new string[] { $"Wrong number of arguments passed to function {target.LimitType} got {args}" })); }
/// <summary> /// Performs the binding of the dynamic set member operation if the target dynamic object cannot bind. /// </summary> /// <param name="target">The target of the dynamic set member operation.</param> /// <param name="value">The value to set to the member.</param> /// <param name="errorSuggestion">The binding result to use if binding fails, or null.</param> /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns> public override DynamicMetaObject FallbackSetMember(DynamicMetaObject target, DynamicMetaObject value, DynamicMetaObject errorSuggestion) { #if !SILVERLIGHT DynamicMetaObject com; if (!BinderHelper.IsWindowsRuntimeObject(target) && ComBinder.TryBindSetMember(this, target, value, out com)) { return(com); } #endif return(BinderHelper.Bind(this, m_binder, new[] { target, value }, m_argumentInfo, errorSuggestion)); }
/// <summary> /// Performs the binding of the dynamic convert operation if the target dynamic object cannot bind. /// </summary> /// <param name="target">The target of the dynamic convert operation.</param> /// <param name="errorSuggestion">The binding result to use if binding fails, or null.</param> /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns> public override DynamicMetaObject FallbackConvert(DynamicMetaObject target, DynamicMetaObject errorSuggestion) { #if ENABLECOMBINDER DynamicMetaObject com; if (!BinderHelper.IsWindowsRuntimeObject(target) && ComBinder.TryConvert(this, target, out com)) { return(com); } #endif return(BinderHelper.Bind(this, _binder, new[] { target }, null, errorSuggestion)); }
/// <summary> /// Performs the binding of the dynamic get member operation if the target dynamic object cannot bind. /// </summary> /// <param name="target">The target of the dynamic get member operation.</param> /// <param name="errorSuggestion">The binding result to use if binding fails, or null.</param> /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns> public override DynamicMetaObject FallbackGetMember(DynamicMetaObject target, DynamicMetaObject errorSuggestion) { #if ENABLECOMBINDER DynamicMetaObject com; if (!BinderHelper.IsWindowsRuntimeObject(target) && ComBinder.TryBindGetMember(this, target, out com, ResultIndexed)) { return(com); } #endif return(BinderHelper.Bind(this, _binder, new[] { target }, _argumentInfo, errorSuggestion)); }
/// <summary> /// Performs the binding of the dynamic invoke member operation if the target dynamic object cannot bind. /// </summary> /// <param name="target">The target of the dynamic invoke member operation.</param> /// <param name="args">The arguments of the dynamic invoke member operation.</param> /// <param name="errorSuggestion">The binding result to use if binding fails, or null.</param> /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns> public override DynamicMetaObject FallbackInvokeMember(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion) { #if ENABLECOMBINDER DynamicMetaObject com; if (!BinderHelper.IsWindowsRuntimeObject(target) && ComBinder.TryBindInvokeMember(this, target, args, out com)) { return(com); } #endif return(BinderHelper.Bind(this, _binder, BinderHelper.Cons(target, args), _argumentInfo, errorSuggestion)); }
/// <summary> /// Performs the binding of the dynamic invoke operation if the target dynamic object cannot bind. /// </summary> /// <param name="target">The target of the dynamic invoke operation.</param> /// <param name="args">The arguments of the dynamic invoke operation.</param> /// <param name="errorSuggestion">The binding result to use if binding fails, or null.</param> /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns> public override DynamicMetaObject FallbackInvoke(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion) { #if !SILVERLIGHT DynamicMetaObject com; if (!BinderHelper.IsWindowsRuntimeObject(target) && ComBinder.TryBindInvoke(this, target, args, out com)) { return(com); } #endif return(BinderHelper.Bind(this, m_binder, BinderHelper.Cons(target, args), m_argumentInfo, errorSuggestion)); }
/// <summary> /// Performs the binding of the dynamic set index operation if the target dynamic object cannot bind. /// </summary> /// <param name="target">The target of the dynamic set index operation.</param> /// <param name="indexes">The arguments of the dynamic set index operation.</param> /// <param name="value">The value to set to the collection.</param> /// <param name="errorSuggestion">The binding result to use if binding fails, or null.</param> /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns> public override DynamicMetaObject FallbackSetIndex(DynamicMetaObject target, DynamicMetaObject[] indexes, DynamicMetaObject value, DynamicMetaObject errorSuggestion) { #if ENABLECOMBINDER DynamicMetaObject com; if (!BinderHelper.IsWindowsRuntimeObject(target) && ComBinder.TryBindSetIndex(this, target, indexes, value, out com)) { return(com); } #endif return(BinderHelper.Bind(this, _binder, BinderHelper.Cons(target, indexes, value), _argumentInfo, errorSuggestion)); }
/// <summary> /// Performs the binding of the dynamic get index operation if the target dynamic object cannot bind. /// </summary> /// <param name="target">The target of the dynamic get index operation.</param> /// <param name="indexes">The arguments of the dynamic get index operation.</param> /// <param name="errorSuggestion">The binding result to use if binding fails, or null.</param> /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns> public override DynamicMetaObject FallbackGetIndex(DynamicMetaObject target, DynamicMetaObject[] indexes, DynamicMetaObject errorSuggestion) { #if ENABLECOMBINDER DynamicMetaObject com; if (!BinderHelper.IsWindowsRuntimeObject(target) && ComBinder.TryBindGetIndex(this, target, indexes, out com)) { return(com); } #endif BinderHelper.ValidateBindArgument(target, nameof(target)); BinderHelper.ValidateBindArgument(indexes, nameof(indexes)); return(BinderHelper.Bind(this, _binder, BinderHelper.Cons(target, indexes), _argumentInfo, errorSuggestion)); }
/// <summary> /// Performs the binding of the dynamic set member operation if the target dynamic object cannot bind. /// </summary> /// <param name="target">The target of the dynamic set member operation.</param> /// <param name="value">The value to set to the member.</param> /// <param name="errorSuggestion">The binding result to use if binding fails, or null.</param> /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns> public override DynamicMetaObject FallbackSetMember(DynamicMetaObject target, DynamicMetaObject value, DynamicMetaObject errorSuggestion) { #if ENABLECOMBINDER DynamicMetaObject com; if (!BinderHelper.IsWindowsRuntimeObject(target) && ComBinder.TryBindSetMember(this, target, value, out com)) { return(com); } #endif BinderHelper.ValidateBindArgument(target, nameof(target)); BinderHelper.ValidateBindArgument(value, nameof(value)); return(BinderHelper.Bind(this, _binder, new[] { target, value }, _argumentInfo, errorSuggestion)); }
/// <summary> /// Performs the binding of the dynamic convert operation if the target dynamic object cannot bind. /// </summary> /// <param name="target">The target of the dynamic convert operation.</param> /// <param name="errorSuggestion">The binding result to use if binding fails, or null.</param> /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns> public override DynamicMetaObject FallbackConvert(DynamicMetaObject target, DynamicMetaObject errorSuggestion) { #if ENABLECOMBINDER DynamicMetaObject com; if (!BinderHelper.IsWindowsRuntimeObject(target) && ComBinder.TryConvert(this, target, out com)) { return(com); } #else BinderHelper.ThrowIfUsingDynamicCom(target); #endif BinderHelper.ValidateBindArgument(target, nameof(target)); return(BinderHelper.Bind(this, _binder, new[] { target }, null, errorSuggestion)); }
/// <summary> /// Performs the binding of the dynamic invoke operation if the target dynamic object cannot bind. /// </summary> /// <param name="target">The target of the dynamic invoke operation.</param> /// <param name="args">The arguments of the dynamic invoke operation.</param> /// <param name="errorSuggestion">The binding result to use if binding fails, or null.</param> /// <returns>The <see cref="DynamicMetaObject"/> representing the result of the binding.</returns> public override DynamicMetaObject FallbackInvoke(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion) { #if ENABLECOMBINDER DynamicMetaObject com; if (!BinderHelper.IsWindowsRuntimeObject(target) && ComBinder.TryConvert(this, target, out com)) { return(com); } #else BinderHelper.ThrowIfUsingDynamicCom(target); #endif BinderHelper.ValidateBindArgument(target, nameof(target)); BinderHelper.ValidateBindArgument(args, nameof(args)); return(BinderHelper.Bind(this, _binder, BinderHelper.Cons(target, args), _argumentInfo, errorSuggestion)); }
public override DynamicMetaObject FallbackSetIndex(DynamicMetaObject target, DynamicMetaObject[] indexes, DynamicMetaObject value, DynamicMetaObject?errorSuggestion) { // First try COM binding. if (ComBinder.TryBindSetIndex(this, target, indexes, value, out var result)) { return(result); } // Defer if any object has no value so that we evaulate their Expressions and nest a // CallSite for the InvokeMember. if (!target.HasValue || !value.HasValue || Array.Exists(indexes, a => !a.HasValue)) { var deferArgs = new DynamicMetaObject[indexes.Length + 2]; indexes.CopyTo(deferArgs.AsSpan(1)); deferArgs[0] = target; deferArgs[^ 1] = value;
public override DynamicMetaObject FallbackGetMember( DynamicMetaObject targetMO, DynamicMetaObject errorSuggestion) { #if !SILVERLIGHT // First try COM binding. DynamicMetaObject result; if (ComBinder.TryBindGetMember(this, targetMO, out result)) { return(result); } #endif // Defer if any object has no value so that we evaulate their // Expressions and nest a CallSite for the InvokeMember. if (!targetMO.HasValue) { return(Defer(targetMO)); } // Find our own binding. var flags = BindingFlags.IgnoreCase | BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public; var members = targetMO.LimitType.GetMember(this.Name, flags); if (members.Length == 1) { return(new DynamicMetaObject( RuntimeHelpers.EnsureObjectResult( Expression.MakeMemberAccess( Expression.Convert(targetMO.Expression, members[0].DeclaringType), members[0])), // Don't need restriction test for name since this // rule is only used where binder is used, which is // only used in sites with this binder.Name. BindingRestrictions.GetTypeRestriction(targetMO.Expression, targetMO.LimitType))); } else { return(errorSuggestion ?? RuntimeHelpers.CreateThrow( targetMO, null, BindingRestrictions.GetTypeRestriction(targetMO.Expression, targetMO.LimitType), typeof(MissingMemberException), "cannot bind member, " + this.Name + ", on object " + targetMO.Value.ToString())); } }
public override DynamicMetaObject FallbackGetIndex(DynamicMetaObject target, DynamicMetaObject[] indexes, DynamicMetaObject errorSuggestion) { if (ComBinder.TryBindGetIndex(this, target, indexes, out DynamicMetaObject result)) { return(result); } if (!target.HasValue || indexes.Any(x => !x.HasValue)) { return(Defer(target, indexes)); } var expression = RuntimeHelpers.EnsureObjectResult(RuntimeHelpers.GetIndexingExpression(target, indexes)); var restrictions = RuntimeHelpers.GetTargetArgsRestrictions(target, indexes, false); return(new DynamicMetaObject(expression, restrictions)); }
public override DynamicMetaObject FallbackInvoke(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject?errorSuggestion) { // First try COM binding. if (ComBinder.TryBindInvoke(this, target, args, out var result)) { return(result); } // Defer if any object has no value so that we evaulate their Expressions and nest a // CallSite for the InvokeMember. if (!target.HasValue || Array.Exists(args, a => !a.HasValue)) { var deferArgs = new DynamicMetaObject[args.Length + 1]; deferArgs[0] = target; args.CopyTo(deferArgs.AsSpan(1)); return(Defer(deferArgs)); } // Find our own binding. if (!target.LimitType.IsSubclassOf(typeof(Delegate))) { return(errorSuggestion ?? RuntimeHelpers.CreateThrow(target, args, BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType), typeof(InvalidOperationException), $"Wrong number of arguments for function -- {target.LimitType} got {args}")); } var parameters = target.LimitType.GetMethod("Invoke") !.GetParameters(); if (parameters.Length != args.Length) { return(errorSuggestion ?? RuntimeHelpers.CreateThrow(target, args, BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType), typeof(InvalidOperationException), $"Wrong number of arguments for function -- {target.LimitType} got {args}")); } // Don't need to check if argument types match parameters. If they don't, users // get an argument conversion error. var callArgs = RuntimeHelpers.ConvertArguments(args, parameters); var expression = Expression.Invoke(Expression.Convert(target.Expression, target.LimitType), callArgs); return(new DynamicMetaObject(RuntimeHelpers.EnsureObjectResult(expression), BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType))); }
public override DynamicMetaObject FallbackInvoke(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion) { if (ComBinder.TryBindInvoke(this, target, args, out DynamicMetaObject res)) { return(res); } return(errorSuggestion ?? new DynamicMetaObject( Expression.Throw( Expression.New( typeof(NotSupportedException).GetConstructor(new[] { typeof(string) }), Expression.Constant(ParserStrings.CannotCall) ), typeof(object) ), target.Restrictions.Merge(BindingRestrictions.Combine(args)) )); }
public override DynamicMetaObject FallbackSetIndex(DynamicMetaObject target, DynamicMetaObject[] indexes, DynamicMetaObject value, DynamicMetaObject errorSuggestion) { if (ComBinder.TryBindSetIndex(this, target, indexes, value, out DynamicMetaObject result)) { return(result); } if (!target.HasValue || !value.HasValue || indexes.Any(x => !x.HasValue)) { return(Defer(target, indexes)); } var arrayAccess = RuntimeHelpers.GetIndexingExpression(target, indexes); var setIndex = Expression.Assign(arrayAccess, Expression.Convert(value.Expression, value.LimitType)); var restrictions = RuntimeHelpers.GetTargetArgsRestrictions(target, indexes, false); return(new DynamicMetaObject(RuntimeHelpers.EnsureObjectResult(setIndex), restrictions)); }
public override DynamicMetaObject FallbackGetIndex( DynamicMetaObject target, DynamicMetaObject[] indexes, DynamicMetaObject errorSuggestion) { #if !SILVERLIGHT // First try COM binding. DynamicMetaObject result; if (ComBinder.TryBindGetIndex(this, target, indexes, out result)) { return(result); } #endif // Defer if any object has no value so that we evaulate their // Expressions and nest a CallSite for the InvokeMember. if (!target.HasValue || indexes.Any((a) => !a.HasValue)) { var deferArgs = new DynamicMetaObject[indexes.Length + 1]; for (int i = 0; i < indexes.Length; i++) { deferArgs[i + 1] = indexes[i]; } deferArgs[0] = target; return(Defer(deferArgs)); } var restrictions = RuntimeHelpers.GetTargetArgsRestrictions( target, indexes, false); if (target.HasValue && target.Value == null) { return(errorSuggestion ?? RuntimeHelpers.CreateThrow(target, indexes, restrictions, typeof(NullReferenceException), "Object reference not set to an instance of an object.")); } var indexingExpr = RuntimeHelpers.EnsureObjectResult( RuntimeHelpers.GetIndexingExpression(target, indexes)); return(new DynamicMetaObject(indexingExpr, restrictions)); }
public override DynamicMetaObject FallbackGetIndex(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject?errorSuggestion) { // First try COM binding. if (ComBinder.TryBindGetIndex(this, target, args, out var result)) { return(result); } // Defer if any object has no value so that we evaulate their Expressions and nest a // CallSite for the InvokeMember. if (!target.HasValue || Array.Exists(args, a => !a.HasValue)) { var deferArgs = new DynamicMetaObject[args.Length + 1]; deferArgs[0] = target; args.CopyTo(deferArgs.AsSpan(1)); return(Defer(deferArgs)); } // Give good error for Cons. if (target.LimitType == typeof(Cons)) { if (args.Length != 1) { return(errorSuggestion ?? RuntimeHelpers.CreateThrow(target, args, BindingRestrictions.Empty, typeof(InvalidOperationException), $"Indexing list takes single index. Got {args.Length}")); } } // Find our own binding. // Conversions created in GetIndexExpression must be consistent with restrictions made in GetTargetArgsRestrictions. var indexingExpr = RuntimeHelpers.EnsureObjectResult(RuntimeHelpers.GetIndexingExpression(target, args)); var restrictions = RuntimeHelpers.GetTargetArgsRestrictions(target, args, false); return(new DynamicMetaObject(indexingExpr, restrictions)); }
internal ComObject(object rcw) { Debug.Assert(ComBinder.IsComObject(rcw)); RuntimeCallableWrapper = rcw; }
public override DynamicMetaObject FallbackInvokeMember( DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion) { DynamicMetaObject result; if (ComBinder.TryBindInvokeMember(this, target, args, out result)) { return(result); } // Defer if any object has no value so that we evaulate their // Expressions and nest a CallSite for the InvokeMember. if (!target.HasValue || args.Any((a) => !a.HasValue)) { var deferArgs = new DynamicMetaObject[args.Length + 1]; for (int i = 0; i < args.Length; i++) { deferArgs[i + 1] = args[i]; } deferArgs[0] = target; return(Defer(deferArgs)); } var flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.Static; var members = Array.Empty <MemberInfo>(); var isStatic = false; if (target.RuntimeType == typeof(UnresolvedType)) { if (runtime.TypeProvider.TryGetType(target.Value as UnresolvedType, out Type type)) { members = type.GetMember(Name, flags); isStatic = true; } } else { members = target.LimitType.GetMember(Name, flags); } if ((members.Length == 1) && (members[0] is PropertyInfo || members[0] is FieldInfo)) { // NEED TO TEST, should check for delegate value too var mem = members[0]; throw new NotImplementedException(); //return new DynamicMetaObject( // Expression.Dynamic( // new RilaInvokeBinder(new CallInfo(args.Length)), // typeof(object), // args.Select(a => a.Expression).AddFirst( // Expression.MakeMemberAccess(this.Expression, mem))); // Don't test for eventinfos since we do nothing with them now. } else { // Get MethodInfos with right arg counts. var methodInfos = members.Where(x => x.MemberType == MemberTypes.Method && ((MethodInfo)x).GetParameters().Length == args.Length); // Get MethodInfos with param types that work for args. This works // except for value args that need to pass to reftype params. // We could detect that to be smarter and then explicitly StrongBox // the args. List <MethodInfo> res = new List <MethodInfo>(); foreach (MethodInfo info in methodInfos) { if (RuntimeHelpers.ParametersMatchArguments(info.GetParameters(), args)) { res.Add(info); } } // False below means generate a type restriction on the MO. // We are looking at the members targetMO's Type. var restrictions = RuntimeHelpers.GetTargetArgsRestrictions(target, args, false); if (res.Count == 0) { var argTypes = args.Select(x => x.RuntimeType.Name).ToArray(); var typesString = string.Join(", ", argTypes); return(errorSuggestion ?? RuntimeHelpers.CreateThrow(target, args, restrictions, typeof(MissingMemberException), new string[] { $"Missing member {typesString} for method \"{Name}\"." })); } // restrictions and conversion must be done consistently. var callArgs = RuntimeHelpers.ConvertArguments(args, res[0].GetParameters()); if (isStatic) { return(new DynamicMetaObject( RuntimeHelpers.EnsureObjectResult(Expression.Call(null, res[0], callArgs)), restrictions)); } return(new DynamicMetaObject( RuntimeHelpers.EnsureObjectResult( Expression.Call( Expression.Convert(target.Expression, target.LimitType), res[0], callArgs)), restrictions)); } }
public override DynamicMetaObject FallbackGetMember(DynamicMetaObject target, DynamicMetaObject errorSuggestion) { DynamicMetaObject result; if (ComBinder.TryBindGetMember(this, target, out result, true)) { return(result); } if (!target.HasValue) { return(Defer(target)); } var flags = BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public; var members = Array.Empty <MemberInfo>(); var isStatic = false; if (target.RuntimeType == typeof(UnresolvedType)) { var unresolved = target.Value as UnresolvedType; if (runtime.TypeProvider.IsAlias(unresolved.Name)) { //Simply pass the name of the member we are trying to access as that is the actual member name return(new DynamicMetaObject( Expression.Constant(new UnresolvedType(Name)), BindingRestrictions.Empty)); } if (runtime.TypeProvider.TryGetType(unresolved, out Type type)) { members = type.GetMember(Name, flags); isStatic = true; } } else { members = target.LimitType.GetMember(Name, flags); } if (members.Length == 1) { if (isStatic) { return(new DynamicMetaObject( RuntimeHelpers.EnsureObjectResult( Expression.MakeMemberAccess(null, members[0])), BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType))); } return(new DynamicMetaObject( RuntimeHelpers.EnsureObjectResult( Expression.MakeMemberAccess( Expression.Convert(target.Expression, members[0].DeclaringType), members[0])), // Don't need restriction test for name since this // rule is only used where binder is used, which is // only used in sites with this binder.Name. BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType))); } else { var error = new string[] { $"Object \"{target.Value.ToString()}\" doesn't contain a member named \"{Name}\"" }; return(errorSuggestion ?? RuntimeHelpers.CreateThrow( target, null, BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType), typeof(MissingMemberException), error)); } }
public override DynamicMetaObject FallbackInvokeMember( DynamicMetaObject targetMO, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion) { #if !NETSTANDARD // First try COM binding. DynamicMetaObject result; if (ComBinder.TryBindInvokeMember(this, targetMO, args, out result)) { return(result); } #endif // Defer if any object has no value so that we evaulate their // Expressions and nest a CallSite for the InvokeMember. if (!targetMO.HasValue || args.Any((a) => !a.HasValue)) { var deferArgs = new DynamicMetaObject[args.Length + 1]; for (int i = 0; i < args.Length; i++) { deferArgs[i + 1] = args[i]; } deferArgs[0] = targetMO; return(Defer(deferArgs)); } // Find our own binding. // Could consider allowing invoking static members from an instance. var flags = BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public; var members = targetMO.LimitType.GetMember(this.Name, flags); var restrictions = RuntimeHelpers.GetTargetArgsRestrictions( targetMO, args, false); // Assigned a Null if (targetMO.HasValue && targetMO.Value == null) { return(RuntimeHelpers.CreateThrow(targetMO, args, restrictions, typeof(NullReferenceException), "Object reference not set to an instance of an object.")); } if ((members.Length == 1) && (members[0] is PropertyInfo || members[0] is FieldInfo)) { // NEED TO TEST, should check for delegate value too var mem = members[0]; var target = new DynamicMetaObject( RuntimeHelpers.EnsureObjectResult( Expression.MakeMemberAccess( Expression.Convert(targetMO.Expression, members[0].DeclaringType), members[0])), // Don't need restriction test for name since this // rule is only used where binder is used, which is // only used in sites with this binder.Name. BindingRestrictions.GetTypeRestriction(targetMO.Expression, targetMO.LimitType)); //If no arguments, to allow scenario like Request.QueryString() if (args == null || args.Length == 0) { return(target); } return(new DynamicMetaObject( RuntimeHelpers.GetIndexingExpression(target, args), restrictions )); // Don't test for eventinfos since we do nothing with them now. } else { bool isExtension = false; // Get MethodInfos with right arg counts. var mi_mems = members. Select(m => m as MethodInfo). Where(m => m is MethodInfo && ((MethodInfo)m).GetParameters().Length == args.Length); // Get MethodInfos with param types that work for args. This works // except for value args that need to pass to reftype params. // We could detect that to be smarter and then explicitly StrongBox // the args. List <MethodInfo> res = new List <MethodInfo>(); foreach (var mem in mi_mems) { if (RuntimeHelpers.ParametersMatchArguments( mem.GetParameters(), args)) { res.Add(mem); } } List <DynamicMetaObject> argList = new List <DynamicMetaObject>(args); //Try extension methods if no methods found if (res.Count == 0) { isExtension = true; argList.Insert(0, targetMO); res = RuntimeHelpers.GetExtensionMethods(this.Name, targetMO, argList.ToArray()); } // False below means generate a type restriction on the MO. // We are looking at the members targetMO's Type. if (res.Count == 0) { return(errorSuggestion ?? RuntimeHelpers.CreateThrow( targetMO, args, restrictions, typeof(MissingMemberException), string.Format("Can't bind member invoke {0}.{1}({2})", targetMO.RuntimeType.Name, this.Name, args.ToString()))); } //If more than one results found, attempt overload resolution MethodInfo mi = null; if (res.Count > 1) { mi = RuntimeHelpers.ResolveOverload(res, argList.ToArray()); } else { mi = res[0]; } // restrictions and conversion must be done consistently. var callArgs = RuntimeHelpers.ConvertArguments( argList.ToArray(), mi.GetParameters()); if (isExtension) { return(new DynamicMetaObject( RuntimeHelpers.EnsureObjectResult( Expression.Call( null, mi, callArgs)), restrictions)); } else { return(new DynamicMetaObject( RuntimeHelpers.EnsureObjectResult( Expression.Call( Expression.Convert(targetMO.Expression, targetMO.LimitType), mi, callArgs)), restrictions)); } // Could hve tried just letting Expr.Call factory do the work, // but if there is more than one applicable method using just // assignablefrom, Expr.Call throws. It does not pick a "most // applicable" method or any method. } }