/// <summary> /// Emits the dynamic method invoke binder. /// </summary> /// <param name="generator">The generator.</param> /// <param name="flag">The binding flags.</param> /// <param name="name">The name.</param> /// <param name="context">The context.</param> /// <param name="argInfo">The arg info.</param> /// <param name="argNames">The arg names.</param> public static void EmitDynamicMethodInvokeBinder(this ILGenerator generator, CSharpBinderFlags flag, string name, IEnumerable<Type> genericParms, Type context, ParameterInfo[] argInfo, IEnumerable<string> argNames) { if (genericParms != null && !genericParms.Any()) genericParms = null; generator.Emit(OpCodes.Ldc_I4, (int)flag); generator.Emit(OpCodes.Ldstr, name); if (genericParms == null) { generator.Emit(OpCodes.Ldnull); } else { generator.EmitArray(typeof(Type), genericParms.Select(arg => (Action<ILGenerator>)(gen => gen.EmitTypeOf(arg))).ToList()); } generator.EmitTypeOf(context); var tList = new List<Action<ILGenerator>> { gen => gen.EmitCreateCSharpArgumentInfo(CSharpArgumentInfoFlags.None) }; tList.AddRange(argInfo.Zip(argNames,(p,n)=>new{p,n}).Select(arg => (Action<ILGenerator>)(gen => { var tStart = CSharpArgumentInfoFlags. UseCompileTimeType; if (arg.p.IsDefined(typeof(DynamicAttribute), true)) { tStart = CSharpArgumentInfoFlags.None; } if (arg.p.IsOut) { tStart |= CSharpArgumentInfoFlags.IsOut; } else if(arg.p.ParameterType.IsByRef) { tStart |= CSharpArgumentInfoFlags.IsRef; } if (!String.IsNullOrEmpty(arg.n)) { tStart |= CSharpArgumentInfoFlags.NamedArgument; } gen.EmitCreateCSharpArgumentInfo(tStart, arg.n); return; }))); generator.EmitArray(typeof(CSharpArgumentInfo), tList); generator.Emit(OpCodes.Call, typeof(Binder).GetMethod("InvokeMember", new[] { typeof(CSharpBinderFlags), typeof(string), typeof(IEnumerable<Type>), typeof(Type), typeof(CSharpArgumentInfo[]) })); }