protected override bool DoDefineMembers() { if (IsGeneric) { foreach (TypeParameter type_param in TypeParameters) { if (!type_param.Resolve(this)) { return(false); } } foreach (TypeParameter type_param in TypeParameters) { if (!type_param.DefineType(this)) { return(false); } } } member_cache = new MemberCache(TypeManager.multicast_delegate_type, this); // FIXME: POSSIBLY make this static, as it is always constant // Type [] const_arg_types = new Type [2]; const_arg_types [0] = TypeManager.object_type; const_arg_types [1] = TypeManager.intptr_type; const MethodAttributes ctor_mattr = MethodAttributes.RTSpecialName | MethodAttributes.SpecialName | MethodAttributes.HideBySig | MethodAttributes.Public; ConstructorBuilder = TypeBuilder.DefineConstructor(ctor_mattr, CallingConventions.Standard, const_arg_types); ConstructorBuilder.DefineParameter(1, ParameterAttributes.None, "object"); ConstructorBuilder.DefineParameter(2, ParameterAttributes.None, "method"); // // HACK because System.Reflection.Emit is lame // IParameterData [] fixed_pars = new IParameterData [] { new ParameterData("object", Parameter.Modifier.NONE), new ParameterData("method", Parameter.Modifier.NONE) }; AParametersCollection const_parameters = new ParametersImported( fixed_pars, new Type[] { TypeManager.object_type, TypeManager.intptr_type }); TypeManager.RegisterMethod(ConstructorBuilder, const_parameters); member_cache.AddMember(ConstructorBuilder, this); ConstructorBuilder.SetImplementationFlags(MethodImplAttributes.Runtime); // // Here the various methods like Invoke, BeginInvoke etc are defined // // First, call the `out of band' special method for // defining recursively any types we need: if (!Parameters.Resolve(this)) { return(false); } // // Invoke method // // Check accessibility foreach (Type partype in Parameters.Types) { if (!IsAccessibleAs(partype)) { Report.SymbolRelatedToPreviousError(partype); Report.Error(59, Location, "Inconsistent accessibility: parameter type `{0}' is less accessible than delegate `{1}'", TypeManager.CSharpName(partype), GetSignatureForError()); return(false); } } ReturnType = ReturnType.ResolveAsTypeTerminal(this, false); if (ReturnType == null) { return(false); } ret_type = ReturnType.Type; if (!IsAccessibleAs(ret_type)) { Report.SymbolRelatedToPreviousError(ret_type); Report.Error(58, Location, "Inconsistent accessibility: return type `" + TypeManager.CSharpName(ret_type) + "' is less " + "accessible than delegate `" + GetSignatureForError() + "'"); return(false); } CheckProtectedModifier(); if (RootContext.StdLib && TypeManager.IsSpecialType(ret_type)) { Method.Error1599(Location, ret_type, Report); return(false); } TypeManager.CheckTypeVariance(ret_type, Variance.Covariant, this); // // We don't have to check any others because they are all // guaranteed to be accessible - they are standard types. // CallingConventions cc = Parameters.CallingConvention; InvokeBuilder = TypeBuilder.DefineMethod("Invoke", mattr, cc, ret_type, Parameters.GetEmitTypes()); InvokeBuilder.SetImplementationFlags(MethodImplAttributes.Runtime); TypeManager.RegisterMethod(InvokeBuilder, Parameters); member_cache.AddMember(InvokeBuilder, this); // // Don't emit async method for compiler generated delegates (e.g. dynamic site containers) // if (TypeManager.iasyncresult_type != null && TypeManager.asynccallback_type != null && !IsCompilerGenerated) { DefineAsyncMethods(cc); } return(true); }
void DefineAsyncMethods(CallingConventions cc) { // // BeginInvoke // Parameters async_parameters = Parameters.MergeGenerated(Parameters, false, new Parameter [] { new Parameter(null, "callback", Parameter.Modifier.NONE, null, Location), new Parameter(null, "object", Parameter.Modifier.NONE, null, Location) }, new Type [] { TypeManager.asynccallback_type, TypeManager.object_type } ); BeginInvokeBuilder = TypeBuilder.DefineMethod("BeginInvoke", mattr, cc, TypeManager.iasyncresult_type, async_parameters.GetEmitTypes()); BeginInvokeBuilder.SetImplementationFlags(MethodImplAttributes.Runtime); TypeManager.RegisterMethod(BeginInvokeBuilder, async_parameters); member_cache.AddMember(BeginInvokeBuilder, this); // // EndInvoke is a bit more interesting, all the parameters labeled as // out or ref have to be duplicated here. // // // Define parameters, and count out/ref parameters // Parameters end_parameters; int out_params = 0; foreach (Parameter p in Parameters.FixedParameters) { if ((p.ModFlags & Parameter.Modifier.ISBYREF) != 0) { ++out_params; } } if (out_params > 0) { Type [] end_param_types = new Type [out_params]; Parameter[] end_params = new Parameter [out_params]; int param = 0; for (int i = 0; i < Parameters.FixedParameters.Length; ++i) { Parameter p = Parameters [i]; if ((p.ModFlags & Parameter.Modifier.ISBYREF) == 0) { continue; } end_param_types [param] = Parameters.Types [i]; end_params [param] = p; ++param; } end_parameters = Parameters.CreateFullyResolved(end_params, end_param_types); } else { end_parameters = Parameters.EmptyReadOnlyParameters; } end_parameters = Parameters.MergeGenerated(end_parameters, false, new Parameter(null, "result", Parameter.Modifier.NONE, null, Location), TypeManager.iasyncresult_type); // // Create method, define parameters, register parameters with type system // EndInvokeBuilder = TypeBuilder.DefineMethod("EndInvoke", mattr, cc, ret_type, end_parameters.GetEmitTypes()); EndInvokeBuilder.SetImplementationFlags(MethodImplAttributes.Runtime); end_parameters.ApplyAttributes(EndInvokeBuilder); TypeManager.RegisterMethod(EndInvokeBuilder, end_parameters); member_cache.AddMember(EndInvokeBuilder, this); }