public DynamicInvokeMethodSignature(MethodSignature concreteSignature) { Debug.Assert(DynamicInvokeMethodThunk.SupportsSignature(concreteSignature)); _signature = concreteSignature; }
public override MethodIL EmitIL() { ILEmitter emitter = new ILEmitter(); var codeStream = emitter.NewCodeStream(); ILCodeLabel returnNullLabel = emitter.NewCodeLabel(); bool hasDynamicInvokeThunk = (_delegateInfo.SupportedFeatures & DelegateFeature.DynamicInvoke) != 0 && DynamicInvokeMethodThunk.SupportsSignature(_delegateInfo.Signature); ILCodeLabel[] labels = new ILCodeLabel[(int)DelegateThunkCollection.MaxThunkKind]; for (DelegateThunkKind i = 0; i < DelegateThunkCollection.MaxThunkKind; i++) { MethodDesc thunk = _delegateInfo.Thunks[i]; if (thunk != null || (i == DelegateThunkKind.DelegateInvokeThunk && hasDynamicInvokeThunk)) { labels[(int)i] = emitter.NewCodeLabel(); } else { labels[(int)i] = returnNullLabel; } } codeStream.EmitLdArg(1); codeStream.EmitSwitch(labels); codeStream.Emit(ILOpcode.br, returnNullLabel); for (DelegateThunkKind i = 0; i < DelegateThunkCollection.MaxThunkKind; i++) { MethodDesc targetMethod = null; // Dynamic invoke thunk is special since we're calling into a shared helper if (i == DelegateThunkKind.DelegateInvokeThunk && hasDynamicInvokeThunk) { Debug.Assert(_delegateInfo.Thunks[i] == null); var sig = new DynamicInvokeMethodSignature(_delegateInfo.Signature); MethodDesc thunk = Context.GetDynamicInvokeThunk(sig); if (thunk.HasInstantiation) { TypeDesc[] inst = DynamicInvokeMethodThunk.GetThunkInstantiationForMethod(_delegateInfo.Type.InstantiateAsOpen().GetMethod("Invoke", null)); targetMethod = Context.GetInstantiatedMethod(thunk, new Instantiation(inst)); } else { targetMethod = thunk; } } else { MethodDesc thunk = _delegateInfo.Thunks[i]; if (thunk != null) { targetMethod = thunk.InstantiateAsOpen(); } } if (targetMethod != null) { codeStream.EmitLabel(labels[(int)i]); codeStream.Emit(ILOpcode.ldftn, emitter.NewToken(targetMethod)); codeStream.Emit(ILOpcode.ret); } } codeStream.EmitLabel(returnNullLabel); codeStream.EmitLdc(0); codeStream.Emit(ILOpcode.conv_i); codeStream.Emit(ILOpcode.ret); return(emitter.Link(this)); }