⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 delegate.cs

📁 C#编译器源代码。Micorsoft开放源代码
💻 CS
📖 第 1 页 / 共 2 页
字号:
//// delegate.cs: Delegate Handler//// Authors://     Ravi Pratap (ravi@ximian.com)//     Miguel de Icaza (miguel@ximian.com)//// Licensed under the terms of the GNU GPL//// (C) 2001 Ximian, Inc (http://www.ximian.com)////using System;using System.Collections;using System.Reflection;using System.Reflection.Emit;using System.Text;namespace Mono.CSharp {	/// <summary>	///   Holds Delegates	/// </summary>	public class Delegate : DeclSpace { 		public Expression ReturnType;		public Parameters      Parameters;		public ConstructorBuilder ConstructorBuilder;		public MethodBuilder      InvokeBuilder;		public MethodBuilder      BeginInvokeBuilder;		public MethodBuilder      EndInvokeBuilder;				Type [] param_types;		Type ret_type;		static string[] attribute_targets = new string [] { "type", "return" };				Expression instance_expr;		MethodBase delegate_method;		ReturnParameter return_attributes;			const int AllowedModifiers =			Modifiers.NEW |			Modifiers.PUBLIC |			Modifiers.PROTECTED |			Modifiers.INTERNAL |		        Modifiers.UNSAFE |			Modifiers.PRIVATE; 		public Delegate (NamespaceEntry ns, TypeContainer parent, Expression type,				 int mod_flags, MemberName name, Parameters param_list,				 Attributes attrs)			: base (ns, parent, name, attrs)		{			this.ReturnType = type;			ModFlags        = Modifiers.Check (AllowedModifiers, mod_flags,							   IsTopLevel ? Modifiers.INTERNAL :							   Modifiers.PRIVATE, name.Location);			Parameters      = param_list;		}		public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)		{			if (a.Target == AttributeTargets.ReturnValue) {				if (return_attributes == null)					return_attributes = new ReturnParameter (InvokeBuilder, Location);				return_attributes.ApplyAttributeBuilder (a, cb);				return;			}			base.ApplyAttributeBuilder (a, cb);		}		public override TypeBuilder DefineType ()		{			if (TypeBuilder != null)				return TypeBuilder;			ec = new EmitContext (this, this, Location, null, null, ModFlags, false);			if (TypeManager.multicast_delegate_type == null && !RootContext.StdLib) {				Namespace system = RootNamespace.Global.GetNamespace ("System", true);				TypeExpr expr = system.Lookup (this, "MulticastDelegate", Location) as TypeExpr;				TypeManager.multicast_delegate_type = expr.ResolveType (ec);			}			if (TypeManager.multicast_delegate_type == null)				throw new InternalErrorException ("System.MulticastDelegate unresolved");			if (IsTopLevel) {				if (TypeManager.NamespaceClash (Name, Location))					return null;								ModuleBuilder builder = CodeGen.Module.Builder;				TypeBuilder = builder.DefineType (					Name, TypeAttr, TypeManager.multicast_delegate_type);			} else {				TypeBuilder builder = Parent.TypeBuilder;				string name = Name.Substring (1 + Name.LastIndexOf ('.'));				TypeBuilder = builder.DefineNestedType (					name, TypeAttr, TypeManager.multicast_delegate_type);			}			TypeManager.AddUserType (this);			return TypeBuilder;		} 		public override bool Define ()		{			MethodAttributes mattr;			int i;			if (ec == null)				throw new InternalErrorException ("Define called before DefineType?");			// 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;			mattr = MethodAttributes.RTSpecialName | MethodAttributes.SpecialName |				MethodAttributes.HideBySig | MethodAttributes.Public;			ConstructorBuilder = TypeBuilder.DefineConstructor (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			//			Parameter [] fixed_pars = new Parameter [2];			fixed_pars [0] = new Parameter (TypeManager.system_object_expr, "object",							Parameter.Modifier.NONE, null, Location);			fixed_pars [1] = new Parameter (TypeManager.system_intptr_expr, "method", 							Parameter.Modifier.NONE, null, Location);			Parameters const_parameters = new Parameters (fixed_pars, null);						TypeManager.RegisterMethod (				ConstructorBuilder,				new InternalParameters (const_arg_types, const_parameters),				const_arg_types);										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:			 			param_types = Parameters.GetParameterInfo (ec);			if (param_types == null)				return false;			//			// Invoke method			//			// Check accessibility			foreach (Type partype in param_types){				if (!Parent.AsAccessible (partype, ModFlags)) {					Report.Error (59, Location,						      "Inconsistent accessibility: parameter type `" +						      TypeManager.CSharpName (partype) + "' is less " +						      "accessible than delegate `" + Name + "'");					return false;				}				if (partype.IsPointer && !UnsafeOK (Parent))					return false;			}						ReturnType = ReturnType.ResolveAsTypeTerminal (ec, false);			if (ReturnType == null)				return false;                        			ret_type = ReturnType.Type;			if (ret_type == null)				return false;			CheckObsoleteType (ReturnType);			if (!Parent.AsAccessible (ret_type, ModFlags)) {				Report.Error (58, Location,					      "Inconsistent accessibility: return type `" +					      TypeManager.CSharpName (ret_type) + "' is less " +					      "accessible than delegate `" + Name + "'");				return false;			}			if (ret_type.IsPointer && !UnsafeOK (Parent))				return false;			if (RootContext.StdLib && (ret_type == TypeManager.arg_iterator_type || ret_type == TypeManager.typed_reference_type)) {				Method.Error1599 (Location, ret_type);				return false;			}			//			// We don't have to check any others because they are all			// guaranteed to be accessible - they are standard types.			//			  			CallingConventions cc = Parameters.GetCallingConvention (); 			mattr = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Virtual; 			InvokeBuilder = TypeBuilder.DefineMethod ("Invoke",  								  mattr,		      								  cc, 								  ret_type,		      								  param_types);			//			// Define parameters, and count out/ref parameters			//			int out_params = 0;			i = 0;			if (Parameters.FixedParameters != null){				int top = Parameters.FixedParameters.Length;				Parameter p;								for (; i < top; i++) {					p = Parameters.FixedParameters [i];					p.DefineParameter (ec, InvokeBuilder, null, i + 1);					if ((p.ModFlags & Parameter.Modifier.ISBYREF) != 0)						out_params++;				}			}			if (Parameters.ArrayParameter != null){				if (TypeManager.param_array_type == null && !RootContext.StdLib) {					Namespace system = RootNamespace.Global.GetNamespace ("System", true);					TypeExpr expr = system.Lookup (this, "ParamArrayAttribute", Location) as TypeExpr;					TypeManager.param_array_type = expr.ResolveType (ec);				}				if (TypeManager.cons_param_array_attribute == null) {					Type [] void_arg = { };					TypeManager.cons_param_array_attribute = TypeManager.GetConstructor (						TypeManager.param_array_type, void_arg);				}				ParameterBuilder pb = InvokeBuilder.DefineParameter (					i + 1, Parameters.ArrayParameter.Attributes,Parameters.ArrayParameter.Name);								pb.SetCustomAttribute (					new CustomAttributeBuilder (TypeManager.cons_param_array_attribute, new object [0]));			}						InvokeBuilder.SetImplementationFlags (MethodImplAttributes.Runtime);			TypeManager.RegisterMethod (InvokeBuilder,						    new InternalParameters (param_types, Parameters),						    param_types);			//			// BeginInvoke			//			int params_num = param_types.Length;			Type [] async_param_types = new Type [params_num + 2];			param_types.CopyTo (async_param_types, 0);			async_param_types [params_num] = TypeManager.asynccallback_type;			async_param_types [params_num + 1] = TypeManager.object_type;			mattr = MethodAttributes.Public | MethodAttributes.HideBySig |				MethodAttributes.Virtual | MethodAttributes.NewSlot;						BeginInvokeBuilder = TypeBuilder.DefineMethod ("BeginInvoke",								       mattr,								       cc,								       TypeManager.iasyncresult_type,								       async_param_types);			i = 0;			if (Parameters.FixedParameters != null){				int top = Parameters.FixedParameters.Length;				Parameter p;								for (i = 0 ; i < top; i++) {					p = Parameters.FixedParameters [i];					p.DefineParameter (ec, BeginInvokeBuilder, null, i + 1);				}			}			if (Parameters.ArrayParameter != null){				Parameter p = Parameters.ArrayParameter;				p.DefineParameter (ec, BeginInvokeBuilder, null, i + 1);				i++;			}			BeginInvokeBuilder.DefineParameter (i + 1, ParameterAttributes.None, "callback");			BeginInvokeBuilder.DefineParameter (i + 2, ParameterAttributes.None, "object");						BeginInvokeBuilder.SetImplementationFlags (MethodImplAttributes.Runtime);			Parameter [] async_params = new Parameter [params_num + 2];			int n = 0;			if (Parameters.FixedParameters != null){				Parameters.FixedParameters.CopyTo (async_params, 0);				n = Parameters.FixedParameters.Length;			}			if (Parameters.ArrayParameter != null)				async_params [n] = Parameters.ArrayParameter;						async_params [params_num] = new Parameter (				TypeManager.system_asynccallback_expr, "callback",								   Parameter.Modifier.NONE, null, Location);			async_params [params_num + 1] = new Parameter (				TypeManager.system_object_expr, "object",								   Parameter.Modifier.NONE, null, Location);			Parameters async_parameters = new Parameters (async_params, null);			TypeManager.RegisterMethod (BeginInvokeBuilder,						    new InternalParameters (async_parameters.GetParameterInfo (ec), async_parameters),						    async_param_types);			//			// EndInvoke is a bit more interesting, all the parameters labeled as			// out or ref have to be duplicated here.			//						Type [] end_param_types = new Type [out_params + 1];			Parameter [] end_params = new Parameter [out_params + 1];			int param = 0; 			if (out_params > 0){				int top = Parameters.FixedParameters.Length;				for (i = 0; i < top; i++){					Parameter p = Parameters.FixedParameters [i];					if ((p.ModFlags & Parameter.Modifier.ISBYREF) == 0)						continue;					end_param_types [param] = param_types [i];					end_params [param] = p;					param++;				}			}			end_param_types [out_params] = TypeManager.iasyncresult_type;			end_params [out_params] = new Parameter (TypeManager.system_iasyncresult_expr, "result", Parameter.Modifier.NONE, null, Location);			//			// Create method, define parameters, register parameters with type system			//			EndInvokeBuilder = TypeBuilder.DefineMethod ("EndInvoke", mattr, cc, ret_type, end_param_types);			EndInvokeBuilder.SetImplementationFlags (MethodImplAttributes.Runtime);			//			// EndInvoke: Label the parameters			//			EndInvokeBuilder.DefineParameter (out_params + 1, ParameterAttributes.None, "result");			for (i = 0; i < end_params.Length-1; i++){				EndInvokeBuilder.DefineParameter (i + 1, end_params [i].Attributes, end_params [i].Name);			}			Parameters end_parameters = new Parameters (end_params, null);			TypeManager.RegisterMethod (				EndInvokeBuilder,				new InternalParameters (end_parameters.GetParameterInfo (ec), end_parameters),				end_param_types);			return true;		}		public override void Emit ()		{			if (OptAttributes != null) {				Parameters.LabelParameters (ec, InvokeBuilder);				OptAttributes.Emit (ec, this);			}			base.Emit ();		}		protected override TypeAttributes TypeAttr {			get {				return Modifiers.TypeAttr (ModFlags, IsTopLevel) |					TypeAttributes.Class | TypeAttributes.Sealed |					base.TypeAttr;			}		}		public override string[] ValidAttributeTargets {			get {				return attribute_targets;			}		}		//TODO: duplicate		protected override bool VerifyClsCompliance (DeclSpace ds)		{			if (!base.VerifyClsCompliance (ds)) {				return false;			}			AttributeTester.AreParametersCompliant (Parameters.FixedParameters, Location);			if (!AttributeTester.IsClsCompliant (ReturnType.Type)) {				Report.Error (3002, Location, "Return type of `{0}' is not CLS-compliant", GetSignatureForError ());			}			return true;		}		//		// Returns the MethodBase for "Invoke" from a delegate type, this is used		// to extract the signature of a delegate.		//		public static MethodInfo GetInvokeMethod (EmitContext ec, Type delegate_type, Location loc)		{			Expression ml = Expression.MemberLookup (				ec, delegate_type, "Invoke", loc);			if (!(ml is MethodGroupExpr)) {				Report.Error (-100, loc, "Internal error: could not find Invoke method!");				return null;			}			return (MethodInfo) (((MethodGroupExpr) ml).Methods [0]);		}				/// <summary>		///  Verifies whether the method in question is compatible with the delegate		///  Returns the method itself if okay and null if not.		/// </summary>		public static MethodBase VerifyMethod (EmitContext ec, Type delegate_type, MethodBase mb,						       Location loc)		{			ParameterData pd = TypeManager.GetParameterData (mb);			int pd_count = pd.Count;			MethodBase invoke_mb = GetInvokeMethod (ec, delegate_type, loc);			if (invoke_mb == null)				return null;			ParameterData invoke_pd = TypeManager.GetParameterData (invoke_mb);			if (invoke_pd.Count != pd_count)				return null;			for (int i = pd_count; i > 0; ) {				i--;				Type invoke_pd_type = invoke_pd.ParameterType (i);				Type pd_type = pd.ParameterType (i);				Parameter.Modifier invoke_pd_type_mod = invoke_pd.ParameterModifier (i);				Parameter.Modifier pd_type_mod = pd.ParameterModifier (i);				if (invoke_pd_type == pd_type &&				    invoke_pd_type_mod == pd_type_mod)					continue;								if (invoke_pd_type.IsSubclassOf (pd_type) && 						invoke_pd_type_mod == pd_type_mod)					if (RootContext.Version == LanguageVersion.ISO_1) {						Report.FeatureIsNotStandardized (loc, "contravariance");						return null;					} else						continue;									return null;			}			Type invoke_mb_retval = ((MethodInfo) invoke_mb).ReturnType;			Type mb_retval = ((MethodInfo) mb).ReturnType;			if (invoke_mb_retval == mb_retval)				return mb;						if (mb_retval.IsSubclassOf (invoke_mb_retval))				if (RootContext.Version == LanguageVersion.ISO_1) {					Report.FeatureIsNotStandardized (loc, "covariance");					return null;				}				else					return mb;						return null;		}		// <summary>		//  Verifies whether the invocation arguments are compatible with the		//  delegate's target method		// </summary>		public static bool VerifyApplicability (EmitContext ec, Type delegate_type,							ArrayList args, Location loc)		{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -