private static object Invoke([NotNull] object target, [NotNull] string methodName, bool staticContext, bool wantReturnValue, params object[] parameters) { if (target == null) { throw new ArgumentNullException("target"); } if (methodName == null) { throw new ArgumentNullException("methodName"); } if (parameters == null) { parameters = new object[] { null }; } // This is the magic sauce that lets the DLR bind static method invocations // dynamically. The current C# 5 compiler (I don't know about Rosyln) does not // support this: // // dynamic t = typeof(Console) // t.Beep() // // This will fail at runtime complaining that TypeInfo does not contain a method // named Beep. By specifying the flags below, this will succeed. I presume this was // cut due to shipping pressure. var binderArgs = new List <CSharpArgumentInfo> { (staticContext) ? CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.IsStaticType | CSharpArgumentInfoFlags.UseCompileTimeType, null) : CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) }; // This is mostly just lip service for the C# binder as we really don't care about the // distinction between null references, numeric/string/null literals and const types // as everything is coming in - at runtime - boxed/byref in the parameters array to // this method. Binding of the target method should succeed regardless. There are a // few scenarios where these details matter - out/ref parameters for example. A null // literal being passed would be invalid for a ref/out; this would need a null ref. for (int i = 0; i < parameters.Length; i++) { object parameter = parameters[i]; CSharpArgumentInfoFlags flags = (parameter == null) ? CSharpArgumentInfoFlags.Constant : CSharpArgumentInfoFlags.UseCompileTimeType; binderArgs.Add(CSharpArgumentInfo.Create(flags, null)); } var callSite = BuildCallSite(methodName, wantReturnValue, parameters, binderArgs); // TODO: build this with expression tree and cache compiled output? Func <object> fn = () => ((Delegate)callSite.Target).DynamicInvoke( (new object[] { callSite, target }).Concat(parameters).ToArray()); return(fn()); }
private void ReduceAssignment(Expression value, CSharpBinderFlags flags, CSharpArgumentInfoFlags leftFlags, CSharpArgumentInfoFlags rightFlags, out CallSiteBinder binder, out IEnumerable <Expression> arguments, out Type[] argumentTypes) { var n = Arguments.Count; var argumentInfos = new CSharpArgumentInfo[n + 2]; var expressions = new Expression[n + 2]; // NB: This is the only place where by-ref passing for the receiver is done in Roslyn; for more // info about the apparent inconsistency see https://github.com/dotnet/roslyn/issues/6818. // We're choosing to be consistent with that behavior until further notice. if (IsReceiverByRef(Object)) { leftFlags |= CSharpArgumentInfoFlags.IsRef; } expressions[0] = Object; argumentInfos[0] = CSharpArgumentInfo.Create(leftFlags, null); argumentTypes = null; CopyArguments(Arguments, argumentInfos, expressions, ref argumentTypes); argumentInfos[n + 1] = CSharpArgumentInfo.Create(rightFlags, null); // TODO: check expressions[n + 1] = value; flags |= Flags; binder = Binder.SetIndex(flags, Context, argumentInfos); arguments = expressions; }
public __CSharpArgumentInfo(CSharpArgumentInfoFlags flags, string name) { }
/// <summary> /// Emits creating the <see cref="CSharpArgumentInfo"></see> /// </summary> /// <param name="generator">The generator.</param> /// <param name="flag">The flag.</param> /// <param name="name">The name.</param> public static void EmitCreateCSharpArgumentInfo(this ILGenerator generator, CSharpArgumentInfoFlags flag, string name = null) { generator.Emit(OpCodes.Ldc_I4, (int)flag); if (String.IsNullOrEmpty(name)) { generator.Emit(OpCodes.Ldnull); } else { generator.Emit(OpCodes.Ldstr, name); } generator.Emit(OpCodes.Call, typeof(CSharpArgumentInfo).GetMethod("Create", new[] { typeof(CSharpArgumentInfoFlags), typeof(string) })); }
private bool Try(CallSiteBinder binder, string member, object[] args, out object result) { ObjectTypeHandle[] argHandles = AdapterTools.Marshal(args); BindingInfo binding = new BindingInfo(binder); const CSharpArgumentInfoFlags flagsRefOrOut = CSharpArgumentInfoFlags.IsRef | CSharpArgumentInfoFlags.IsOut; ObjectTypeHandle resHandle; try{ resHandle = Adapter.InvokeMember(member, ref argHandles, binding.ArgumentFlags.Skip(1).Select(f => (f & flagsRefOrOut) != 0).ToArray()); }catch (MissingMethodException) { result = null; return(false); } AdapterTools.Unmarshal(argHandles).CopyTo(args, 0); result = AdapterTools.Unmarshal(resHandle); return(true); }
public ObjectHandle InvokeMember(BindingInfo binding, ref ObjectHandle[] args) { object[] oArgs = AdapterTools.Unmarshal(args); var binder = binding.CreateBinder(); object[] argsObj = new object[args.Length + 1]; argsObj[0] = Value; oArgs.CopyTo(argsObj, 1); Expression dynExpr; object ret; const CSharpArgumentInfoFlags flagsRefOrOut = CSharpArgumentInfoFlags.IsRef | CSharpArgumentInfoFlags.IsOut; var argsConst = Expression.Constant(argsObj); var argsExp = argsObj.Select((o, i) => (binding.ArgumentFlags[i] & flagsRefOrOut) != 0?(Expression)Expression.ArrayAccess(argsConst, Expression.Constant(i)):Expression.Constant(o)); try{ if ((binding.Flags & CSharpBinderFlags.ResultDiscarded) != 0) { dynExpr = Expression.Dynamic(binder, typeof(void), argsExp); Expression.Lambda <Action>(dynExpr).Compile().Invoke(); ret = null; } else { dynExpr = Expression.Dynamic(binder, typeof(object), argsExp); ret = Expression.Lambda <Func <object> >(dynExpr).Compile().Invoke(); } }catch (TargetInvocationException e) { throw e.InnerException; } for (int i = 0; i < binding.ArgumentFlags.Length; i++) { if ((binding.ArgumentFlags[i] & flagsRefOrOut) == 0) { argsObj[i] = null; } } Array.Copy(argsObj, 1, oArgs, 0, oArgs.Length); args = AdapterTools.Marshal(oArgs); return(AdapterTools.Marshal(ret)); }
/// <summary> /// DynamicOperatorRewriter in EE generates call to this method to dynamically invoke a property setter /// with no arguments. /// </summary> /// <typeparam name="TObject">Type of object on which property is defined.</typeparam> /// <typeparam name="TValue">Type of value property needs to be set to.</typeparam> /// <param name="obj">Object on which property is defined.</param> /// <param name="propName">Name of a property to invoke.</param> /// <param name="value">Value property needs to be set to.</param> /// <param name="valueFlags"></param> /// <param name="accessibilityContext">Type that determines context in which method should be called.</param> /// <returns>Result of property invocation.</returns> public static object TrySetMemberValue <TObject, TValue>( TObject obj, string propName, TValue value, CSharpArgumentInfoFlags valueFlags, Type accessibilityContext) { CSharpArgumentInfo targetArgInfo = CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null); CSharpArgumentInfo valueArgInfo = CSharpArgumentInfo.Create(valueFlags, null); CSharpSetMemberBinder binder = new CSharpSetMemberBinder( propName, false, // isCompoundAssignment false, // isChecked accessibilityContext, new CSharpArgumentInfo[] { targetArgInfo, valueArgInfo }); var site = CallSite <Func <CallSite, TObject, TValue, object> > .Create(binder); return(site.Target(site, obj, value)); }
public static object TryEvalBinaryOperators <T1, T2>( T1 arg1, T2 arg2, CSharpArgumentInfoFlags arg1Flags, CSharpArgumentInfoFlags arg2Flags, ExpressionType opKind, Type accessibilityContext) { CSharpArgumentInfo arg1Info = CSharpArgumentInfo.Create(arg1Flags, null); CSharpArgumentInfo arg2Info = CSharpArgumentInfo.Create(arg2Flags, null); CSharpBinaryOperationBinder binder = new CSharpBinaryOperationBinder( opKind, false, // isChecked CSharpBinaryOperationFlags.None, accessibilityContext, new CSharpArgumentInfo[] { arg1Info, arg2Info }); var site = CallSite <Func <CallSite, T1, T2, object> > .Create(binder); return(site.Target(site, arg1, arg2)); }
private void ReduceAssignment(Expression value, CSharpBinderFlags flags, CSharpArgumentInfoFlags leftFlags, CSharpArgumentInfoFlags rightFlags, out CallSiteBinder binder, out IEnumerable <Expression> arguments, out Type[] argumentTypes) { var n = Arguments.Count; var argumentInfos = new CSharpArgumentInfo[n + 2]; var expressions = new Expression[n + 2]; // NB: By-ref passing for the receiver seems to be omitted in Roslyn here; see https://github.com/dotnet/roslyn/issues/6818. // We're choosing to be consistent with that behavior until further notice. expressions[0] = Object; argumentInfos[0] = CSharpArgumentInfo.Create(leftFlags, null); argumentTypes = null; CopyArguments(Arguments, argumentInfos, expressions, ref argumentTypes); argumentInfos[n + 1] = CSharpArgumentInfo.Create(rightFlags, null); // TODO: check expressions[n + 1] = value; flags |= Flags; binder = Binder.SetMember(flags, Name, Context, argumentInfos); arguments = expressions; }
CSharpArgumentInfo (CSharpArgumentInfoFlags flags, string name) { this.flags = flags; this.name = name; }
private CSharpArgumentInfo(CSharpArgumentInfoFlags flags, string name) { Flags = flags; Name = name; }
public static extern CSharpArgumentInfo Create(CSharpArgumentInfoFlags flags, string name);
static CSharpArgumentInfo \u202E([In] CSharpArgumentInfoFlags obj0, [In] string obj1) { // ISSUE: unable to decompile the method. }
internal Expression ReduceAssignment(Expression value, CSharpBinderFlags flags, CSharpArgumentInfoFlags leftFlags = CSharpArgumentInfoFlags.None, CSharpArgumentInfoFlags rightFlags = CSharpArgumentInfoFlags.None) { var binder = default(CallSiteBinder); var arguments = default(IEnumerable<Expression>); var argumentTypes = default(Type[]); ReduceAssignment(value, flags, leftFlags, rightFlags, out binder, out arguments, out argumentTypes); return DynamicHelpers.MakeDynamic(Type, binder, arguments, argumentTypes); }
static CSharpArgumentInfo \u200D([In] CSharpArgumentInfoFlags obj0, [In] string obj1) { // ISSUE: unable to decompile the method. }
/// <summary> /// Emits creating the <see cref="CSharpArgumentInfo"></see> /// </summary> /// <param name="generator">The generator.</param> /// <param name="flag">The flag.</param> /// <param name="name">The name.</param> public static void EmitCreateCSharpArgumentInfo(this ILGenerator generator, CSharpArgumentInfoFlags flag, string name = null) { generator.Emit(OpCodes.Ldc_I4, (int)flag); if (String.IsNullOrEmpty(name)) generator.Emit(OpCodes.Ldnull); else generator.Emit(OpCodes.Ldstr, name); generator.Emit(OpCodes.Call, typeof(CSharpArgumentInfo).GetMethod("Create", new[] { typeof(CSharpArgumentInfoFlags), typeof(string) })); }
static CSharpArgumentInfo \u202A([In] CSharpArgumentInfoFlags obj0, [In] string obj1) { // ISSUE: unable to decompile the method. }
/// <summary> /// Creates an object representing a dynamically bound argument with the specified name and the specified argument flags. /// </summary> /// <param name="expression">The expression representing the value of the argument.</param> /// <param name="name">The name of the argument to bind.</param> /// <param name="argumentFlags">The argument flags denoting various properties about the dynamically bound argument.</param> /// <returns>An object representing a dynamically bound argument.</returns> public static DynamicCSharpArgument DynamicArgument(Expression expression, string name, CSharpArgumentInfoFlags argumentFlags) { RequiresCanRead(expression, nameof(expression)); return(new DynamicCSharpArgument(argumentFlags, name, expression)); }
internal DynamicCSharpArgument(CSharpArgumentInfoFlags flags, string name, Expression expression) { Flags = flags; Name = name; Expression = expression; }
static CSharpArgumentInfo \u202B([In] CSharpArgumentInfoFlags obj0, [In] string obj1) { // ISSUE: unable to decompile the method. }
public void Create_ResultNotNull(CSharpArgumentInfoFlags flag, string name) { Assert.NotNull(CSharpArgumentInfo.Create(flag, name)); }
<ImportInputs>o__SiteContainer14.<>p__Site16 = CallSite<Func<CallSite, object, object>>.Create(Microsoft.CSharp.RuntimeBinder.Binder.GetMember(CSharpBinderFlags.None, "Value2", typeof(xe8f63ddfa545c93b), new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) }));
static CSharpArgumentInfo \u202E([In] CSharpArgumentInfoFlags obj0, [In] string obj1) { // ISSUE: unable to decompile the method. }
private CSharpArgumentInfo(CSharpArgumentInfoFlags flags, string name) { _flags = flags; _name = name; }
static CSharpArgumentInfo \u200B([In] CSharpArgumentInfoFlags obj0, [In] string obj1) { // ISSUE: unable to decompile the method. }
CSharpArgumentInfo(CSharpArgumentInfoFlags flags, string name) { this.flags = flags; this.name = name; }
internal Expression ReduceAssignment(Expression value, CSharpBinderFlags flags, CSharpArgumentInfoFlags leftFlags = CSharpArgumentInfoFlags.None, CSharpArgumentInfoFlags rightFlags = CSharpArgumentInfoFlags.None) { var binder = default(CallSiteBinder); var arguments = default(IEnumerable <Expression>); var argumentTypes = default(Type[]); ReduceAssignment(value, flags, leftFlags, rightFlags, out binder, out arguments, out argumentTypes); return(DynamicHelpers.MakeDynamic(Type, binder, arguments, argumentTypes)); }
private void ReduceAssignment(Expression value, CSharpBinderFlags flags, CSharpArgumentInfoFlags leftFlags, CSharpArgumentInfoFlags rightFlags, out CallSiteBinder binder, out IEnumerable<Expression> arguments, out Type[] argumentTypes) { var n = Arguments.Count; var argumentInfos = new CSharpArgumentInfo[n + 2]; var expressions = new Expression[n + 2]; // NB: This is the only place where by-ref passing for the receiver is done in Roslyn; for more // info about the apparent inconsistency see https://github.com/dotnet/roslyn/issues/6818. // We're choosing to be consistent with that behavior until further notice. if (IsReceiverByRef(Object)) { leftFlags |= CSharpArgumentInfoFlags.IsRef; } expressions[0] = Object; argumentInfos[0] = CSharpArgumentInfo.Create(leftFlags, null); argumentTypes = null; CopyArguments(Arguments, argumentInfos, expressions, ref argumentTypes); argumentInfos[n + 1] = CSharpArgumentInfo.Create(rightFlags, null); // TODO: check expressions[n + 1] = value; flags |= Flags; binder = Binder.SetIndex(flags, Context, argumentInfos); arguments = expressions; }
public BindingInfo(CallSiteBinder binder) { Context = binder.GetCallingContext(); var argInfo = binder.GetArgumentInfo(); if (argInfo != null) { ArgumentFlags = argInfo.Select(a => a.GetFlags()).ToArray(); ArgumentNames = argInfo.Select(a => a.GetName()).ToArray(); } else { ArgumentFlags = new CSharpArgumentInfoFlags[0]; ArgumentNames = new string[0]; } Flags = binder.GetBinderFlags(); var bo = binder as BinaryOperationBinder; if (bo != null) { BinderType = BinderTypeEnum.BinaryOperation; ReturnType = bo.ReturnType; Operation = bo.Operation; return; } var c = binder as ConvertBinder; if (c != null) { BinderType = BinderTypeEnum.Convert; ReturnType = c.ReturnType; Type = c.Type; Explicit = c.Explicit; return; } var gi = binder as GetIndexBinder; if (gi != null) { BinderType = BinderTypeEnum.GetIndex; //CallInfo = gi.CallInfo; ReturnType = gi.ReturnType; return; } var gm = binder as GetMemberBinder; if (gm != null) { BinderType = BinderTypeEnum.GetMember; IgnoreCase = gm.IgnoreCase; Name = gm.Name; ReturnType = gm.ReturnType; return; } var i = binder as InvokeBinder; if (i != null) { BinderType = BinderTypeEnum.Invoke; //CallInfo = i.CallInfo; return; } var im = binder as InvokeMemberBinder; if (im != null) { BinderType = BinderTypeEnum.InvokeMember; //CallInfo = im.CallInfo; IgnoreCase = im.IgnoreCase; Name = im.Name; ReturnType = im.ReturnType; TypeArguments = im.GetTypeArguments().ToArray(); return; } var si = binder as SetIndexBinder; if (si != null) { BinderType = BinderTypeEnum.SetIndex; //CallInfo = si.CallInfo; ReturnType = si.ReturnType; return; } var sm = binder as SetMemberBinder; if (sm != null) { BinderType = BinderTypeEnum.SetMember; IgnoreCase = sm.IgnoreCase; Name = sm.Name; ReturnType = sm.ReturnType; return; } }
public static __CSharpArgumentInfo Create(CSharpArgumentInfoFlags flags, string name) { return new __CSharpArgumentInfo { flags = flags, name = name }; }
private void ReduceAssignment(Expression value, CSharpBinderFlags flags, CSharpArgumentInfoFlags leftFlags, CSharpArgumentInfoFlags rightFlags, out CallSiteBinder binder, out IEnumerable<Expression> arguments, out Type[] argumentTypes) { var n = Arguments.Count; var argumentInfos = new CSharpArgumentInfo[n + 2]; var expressions = new Expression[n + 2]; // NB: By-ref passing for the receiver seems to be omitted in Roslyn here; see https://github.com/dotnet/roslyn/issues/6818. // We're choosing to be consistent with that behavior until further notice. expressions[0] = Object; argumentInfos[0] = CSharpArgumentInfo.Create(leftFlags, null); argumentTypes = null; CopyArguments(Arguments, argumentInfos, expressions, ref argumentTypes); argumentInfos[n + 1] = CSharpArgumentInfo.Create(rightFlags, null); // TODO: check expressions[n + 1] = value; flags |= Flags; binder = Binder.SetMember(flags, Name, Context, argumentInfos); arguments = expressions; }
public static __CSharpArgumentInfo Create(CSharpArgumentInfoFlags flags, string name) { return(new __CSharpArgumentInfo { flags = flags, name = name }); }
/// <summary> /// Initializes a new instance of the <see cref="CSharpArgumentInfo"/> class. /// </summary> /// <param name="flags">The flags for the argument.</param> /// <param name="name">The name of the argument, if named; otherwise null.</param> public static CSharpArgumentInfo Create(CSharpArgumentInfoFlags flags, string name) { return(new CSharpArgumentInfo(flags, name)); }
internal Expression ReduceAssignment(Expression value, CSharpBinderFlags flags, CSharpArgumentInfoFlags leftFlags = CSharpArgumentInfoFlags.None, CSharpArgumentInfoFlags rightFlags = CSharpArgumentInfoFlags.None) { ReduceAssignment(value, flags, leftFlags, rightFlags, out CallSiteBinder binder, out IEnumerable <Expression> arguments, out Type[] argumentTypes);
public static CSharpArgumentInfo Create (CSharpArgumentInfoFlags flags, string name) { return new CSharpArgumentInfo (flags, name); }
public bool HasFlag(CSharpArgumentInfoFlags flag) => (Flags & flag) != 0;
static CSharpArgumentInfo \u202C([In] CSharpArgumentInfoFlags obj0, [In] string obj1) { // ISSUE: unable to decompile the method. }
/// <summary> /// Creates an object representing a dynamically bound argument with the specified name and the specified argument flags. /// </summary> /// <param name="expression">The expression representing the value of the argument.</param> /// <param name="name">The name of the argument to bind.</param> /// <param name="argumentFlags">The argument flags denoting various properties about the dynamically bound argument.</param> /// <returns>An object representing a dynamically bound argument.</returns> public static DynamicCSharpArgument DynamicArgument(Expression expression, string name, CSharpArgumentInfoFlags argumentFlags) { RequiresCanRead(expression, nameof(expression)); return new DynamicCSharpArgument(argumentFlags, name, expression); }
internal BoundExpression GetArgumentInfo( MethodSymbol argumentInfoFactory, BoundExpression boundArgument, string name, RefKind refKind, bool isStaticType) { CSharpArgumentInfoFlags flags = 0; if (isStaticType) { flags |= CSharpArgumentInfoFlags.IsStaticType; } if (name != null) { flags |= CSharpArgumentInfoFlags.NamedArgument; } Debug.Assert(refKind == RefKind.None || refKind == RefKind.Ref || refKind == RefKind.Out, "unexpected refKind in dynamic"); // by-ref type doesn't trigger dynamic dispatch and it can't be a null literal => set UseCompileTimeType if (refKind == RefKind.Out) { flags |= CSharpArgumentInfoFlags.IsOut | CSharpArgumentInfoFlags.UseCompileTimeType; } else if (refKind == RefKind.Ref) { flags |= CSharpArgumentInfoFlags.IsRef | CSharpArgumentInfoFlags.UseCompileTimeType; } var argType = boundArgument.Type; // Check "literal" constant. // What the runtime binder does with this LiteralConstant flag is just to create a constant, // which is a compelling enough reason to make sure that on the production end of the binder // data, we do the inverse (i.e., use the LiteralConstant flag whenever we encounter a constant // argument. // And in fact, the bug being fixed with this change is that the compiler will consider constants // for numeric and enum conversions even if they are not literals (such as, (1-1) --> enum), but // the runtime binder didn't. So we do need to set this flag whenever we see a constant. // But the complication is that null values lose their type when they get to the runtime binder, // and so we need a way to distinguish a null constant of any given type from the null literal. // The design is simple! We use UseCompileTimeType to determine whether we care about the type of // a null constant argument, so that the null literal gets "LiteralConstant" whereas every other // constant gets "LiteralConstant | UseCompileTimeType". Because obviously UseCompileTimeType is // wrong for the null literal. // We care, because we want to prevent this from working: // // const C x = null; // class C { public void M(SomeUnrelatedReferenceType x) { } } // ... // dynamic d = new C(); d.M(x); // This will pass a null constant and the type is gone! // // as well as the alternative where x is a const null of type object. if (boundArgument.ConstantValue != null) { flags |= CSharpArgumentInfoFlags.Constant; } // Check compile time type. // See also DynamicRewriter::GenerateCallingObjectFlags. if ((object)argType != null && !argType.IsDynamic()) { flags |= CSharpArgumentInfoFlags.UseCompileTimeType; } return(_factory.Call(null, argumentInfoFactory, _factory.Literal((int)flags), _factory.Literal(name))); }
private CSharpArgumentInfo(CSharpArgumentInfoFlags flags, string name) { this.Flags = flags; this.Name = name; }