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

📄 anonymous.cs

📁 C#编译器源代码。Micorsoft开放源代码
💻 CS
📖 第 1 页 / 共 3 页
字号:
//// anonymous.cs: Support for anonymous methods//// Author://   Miguel de Icaza (miguel@ximain.com)//// (C) 2003, 2004 Novell, Inc.//// TODO: Ideally, we should have the helper classes emited as a hierarchy to map// their nesting, and have the visibility set to private, instead of NestedAssembly//////using System;using System.Text;using System.Collections;using System.Reflection;using System.Reflection.Emit;namespace Mono.CSharp {	public abstract class AnonymousContainer : Expression	{		// Used to generate unique method names.		protected static int anonymous_method_count;		    		// An array list of AnonymousMethodParameter or null		public Parameters Parameters;		//		// The block that makes up the body for the anonymous mehtod		//		public ToplevelBlock Block;		//		// The container block for this anonymous method.		//		public Block ContainingBlock;		//		// The implicit method we create		//		public Method method;		protected MethodInfo invoke_mb;				// The emit context for the anonymous method		public EmitContext aec;		public InternalParameters amp;		protected bool unreachable;		//		// The modifiers applied to the method, we aggregate them		//		protected int method_modifiers = Modifiers.PRIVATE;				//		// During the resolve stage of the anonymous method body,		// we discover the actual scope where we are hosted, or		// null to host the method in the same class		//		public ScopeInfo Scope;		//		// Points to our container anonymous method if its present		//		public AnonymousContainer ContainerAnonymousMethod;			protected AnonymousContainer (Parameters parameters, ToplevelBlock container,					      ToplevelBlock block, Location l)		{			Parameters = parameters;			Block = block;			loc = l;			//			// The order is important: this setups the CaptureContext tree hierarchy.			//			if (container == null) {				Report.Error (1706, l, "Anonymous methods are not allowed in attribute declaration");				return;			}			container.SetHaveAnonymousMethods (l, this);			block.SetHaveAnonymousMethods (l, this);		}		protected AnonymousContainer (Parameters parameters, ToplevelBlock container,					      Location l):			this (parameters, container, new ToplevelBlock (container, parameters, l), l)		{		}		public override Expression DoResolve (EmitContext ec)		{			//			// Set class type, set type			//			eclass = ExprClass.Value;						//			// This hack means `The type is not accessible			// anywhere', we depend on special conversion			// rules.			// 			type = TypeManager.anonymous_method_type;			return this;		}		protected abstract bool CreateMethodHost (EmitContext ec);		public abstract void CreateScopeType (EmitContext ec, ScopeInfo scope);		public abstract bool IsIterator {			get;		}	}	public class AnonymousMethod : AnonymousContainer	{		public AnonymousMethod (Parameters parameters, ToplevelBlock container,					ToplevelBlock block, Location l)			: base (parameters, container, block, l)		{		}		public override bool IsIterator {			get { return false; }		}		public override void Emit (EmitContext ec)		{			// nothing, as we only exist to not do anything.		}		//		// Creates the host for the anonymous method		//		protected override bool CreateMethodHost (EmitContext ec)		{			//			// Crude hack follows: we replace the TypeBuilder during the			// definition to get the method hosted in the right class			//						TypeBuilder current_type = ec.TypeContainer.TypeBuilder;			TypeBuilder type_host = (Scope == null ) // || Scope.ScopeTypeBuilder == null)				? current_type : Scope.ScopeTypeBuilder;			if (current_type == null)				throw new Exception ("The current_type is null");						if (type_host == null)				throw new Exception (String.Format ("Type host is null, Scope is {0}", Scope == null ? "null" : "Not null"));			if (current_type != type_host)				method_modifiers = Modifiers.INTERNAL;			if (current_type == type_host && ec.IsStatic){				method_modifiers |= Modifiers.STATIC;				current_type = null;			} 			method = new Method (				(TypeContainer) ec.TypeContainer,				new TypeExpression (invoke_mb.ReturnType, loc),				method_modifiers, false, new MemberName ("<#AnonymousMethod>" + anonymous_method_count++, loc),				Parameters, null);			method.Block = Block;						//			// Swap the TypeBuilder while we define the method, then restore			//			if (current_type != null)				ec.TypeContainer.TypeBuilder = type_host;			bool res = method.Define ();			if (current_type != null)				ec.TypeContainer.TypeBuilder = current_type;			return res;		}				void Error_ParameterMismatch (Type t)		{			Report.Error (1661, loc, "Anonymous method could not be converted to delegate `" +				      "{0}' since there is a parameter mismatch", t);		}		//		// Returns true if this anonymous method can be implicitly		// converted to the delegate type `delegate_type'		//		public Expression Compatible (EmitContext ec, Type delegate_type, bool probe)		{			//			// At this point its the first time we know the return type that is 			// needed for the anonymous method.  We create the method here.			//			invoke_mb = (MethodInfo) Delegate.GetInvokeMethod (ec, delegate_type, loc);			ParameterData invoke_pd = TypeManager.GetParameterData (invoke_mb);			if (Parameters == null){				int i, j;								//				// We provide a set of inaccessible parameters				//				int params_idx = -1;				for (i = 0; i < invoke_pd.Count; i++){					if (invoke_pd.ParameterModifier (i) == Parameter.Modifier.PARAMS)						params_idx = i;				}				int n = invoke_pd.Count - (params_idx != -1 ? 1 : 0);				Parameter [] fixedpars = new Parameter [n];								for (i =  j = 0; i < invoke_pd.Count; i++){					if (invoke_pd.ParameterModifier (i) == Parameter.Modifier.PARAMS)						continue;					fixedpars [j] = new Parameter (						new TypeExpression (invoke_pd.ParameterType (i), loc),						"+" + j, invoke_pd.ParameterModifier (i), null, loc);					j++;				}								Parameter variable = null;				if (params_idx != -1){					variable = new Parameter (						new TypeExpression (invoke_pd.ParameterType (params_idx), loc),						"+" + params_idx, invoke_pd.ParameterModifier (params_idx), null, loc);				}				Parameters = new Parameters (fixedpars, variable);			}						//			// First, parameter types of `delegate_type' must be compatible			// with the anonymous method.			//			amp = new InternalParameters (Parameters.GetParameterInfo (ec), Parameters);						if (amp.Count != invoke_pd.Count){				if (!probe){					Report.Error (1593, loc, "Delegate `{0}' does not take `{1}' arguments",						TypeManager.CSharpName (delegate_type), amp.Count);					Error_ParameterMismatch (delegate_type);				}				return null;			}						for (int i = 0; i < amp.Count; i++){				Parameter.Modifier amp_mod = amp.ParameterModifier (i);				if (!probe) {					if ((amp_mod & (Parameter.Modifier.OUT | Parameter.Modifier.REF)) != 0){						Report.Error (1677, loc, "Parameter `{0}' should not be declared with the `{1}' keyword", 							i+1, amp.ModifierDesc (i));						Error_ParameterMismatch (delegate_type);						return null;					}					if (amp_mod != invoke_pd.ParameterModifier (i)){						Report.Error (1676, loc, "Parameter `{0}' must be declared with the `{1}' keyword",							i+1, Parameter.GetModifierSignature (invoke_pd.ParameterModifier (i)));						Error_ParameterMismatch (delegate_type);						return null;					}									if (amp.ParameterType (i) != invoke_pd.ParameterType (i)){						Report.Error (1678, loc, "Parameter `{0}' is declared as type `{1}' but should be `{2}'",							i+1,							TypeManager.CSharpName (amp.ParameterType (i)),							TypeManager.CSharpName (invoke_pd.ParameterType (i)));						Error_ParameterMismatch (delegate_type);						return null;					}				}			}			//			// If we are only probing, return ourselves			//			if (probe)				return this;						//			// Second: the return type of the delegate must be compatible with 			// the anonymous type.   Instead of doing a pass to examine the block			// we satisfy the rule by setting the return type on the EmitContext			// to be the delegate type return type.			//			//MethodBuilder builder = method_data.MethodBuilder;			//ILGenerator ig = builder.GetILGenerator ();						aec = new EmitContext (				ec.TypeContainer, ec.DeclSpace, loc, null,				invoke_mb.ReturnType,				/* REVIEW */ (ec.InIterator ? Modifiers.METHOD_YIELDS : 0) |				(ec.InUnsafe ? Modifiers.UNSAFE : 0) |				(ec.IsStatic ? Modifiers.STATIC : 0),				/* No constructor */ false);			aec.CurrentAnonymousMethod = this;			ContainerAnonymousMethod = ec.CurrentAnonymousMethod;			ContainingBlock = ec.CurrentBlock;			if (aec.ResolveTopBlock (ec, Block, amp, null, out unreachable))				return new AnonymousDelegate (this, delegate_type, loc).Resolve (ec);			return null;		}		public override string ExprClassName {			get {				return "anonymous method";			}		}		public MethodBuilder GetMethodBuilder ()		{			return method.MethodData.MethodBuilder;		}		public override string GetSignatureForError ()		{			string s = TypeManager.CSharpSignature (invoke_mb);			return s.Substring (0, s.IndexOf (".Invoke("));		}				public bool EmitMethod (EmitContext ec)		{			if (!CreateMethodHost (ec))				return false;			MethodBuilder builder = GetMethodBuilder ();			ILGenerator ig = builder.GetILGenerator ();			aec.ig = ig;						Parameters.LabelParameters (aec, builder);			//			// Adjust based on the computed state of the			// method from CreateMethodHost						aec.MethodIsStatic = (method_modifiers & Modifiers.STATIC) != 0;						aec.EmitMeta (Block, amp);			aec.EmitResolvedTopBlock (Block, unreachable);			return true;		}		public override void CreateScopeType (EmitContext ec, ScopeInfo scope)		{			TypeBuilder container = ec.TypeContainer.TypeBuilder;			string name = String.Format ("<>AnonHelp<{0}>", scope.id);			scope.ScopeTypeBuilder = container.DefineNestedType (				name, TypeAttributes.AutoLayout | TypeAttributes.Class |				TypeAttributes.NestedAssembly, TypeManager.object_type, null);			Type [] constructor_types = TypeManager.NoTypes;			Parameters constructor_parameters = Parameters.EmptyReadOnlyParameters;			scope.ScopeConstructor = scope.ScopeTypeBuilder.DefineConstructor (				MethodAttributes.Public | MethodAttributes.HideBySig |				MethodAttributes.SpecialName | MethodAttributes.RTSpecialName,				CallingConventions.HasThis, constructor_types);			InternalParameters parameter_info = new InternalParameters (constructor_types, constructor_parameters);			TypeManager.RegisterMethod (scope.ScopeConstructor, parameter_info, constructor_types);			ILGenerator cig = scope.ScopeConstructor.GetILGenerator ();			cig.Emit (OpCodes.Ldarg_0);			cig.Emit (OpCodes.Call, TypeManager.object_ctor);			cig.Emit (OpCodes.Ret);		}		public static void Error_AddressOfCapturedVar (string name, Location loc)		{			Report.Error (1686, loc,				"Local variable `{0}' or its members cannot have their address taken and be used inside an anonymous method block",				name);		}	}	//	// This will emit the code for the delegate, as well delegate creation on the host	//	public class AnonymousDelegate : DelegateCreation {		AnonymousMethod am;		public AnonymousDelegate (AnonymousMethod am, Type target_type, Location l)		{			type = target_type;			loc = l;			this.am = am;		}		public override Expression DoResolve (EmitContext ec)		{			eclass = ExprClass.Value;			return this;		}				public override void Emit (EmitContext ec)		{			if (!am.EmitMethod (ec))				return;			//			// Now emit the delegate creation.			//			if ((am.method.ModFlags & Modifiers.STATIC) == 0)				delegate_instance_expression = new AnonymousInstance (am);						Expression ml = Expression.MemberLookup (ec, type, ".ctor", loc);			constructor_method = ((MethodGroupExpr) ml).Methods [0];			delegate_method = am.GetMethodBuilder ();			base.Emit (ec);		}		class AnonymousInstance : Expression {			AnonymousMethod am;						public AnonymousInstance (AnonymousMethod am)			{				this.am = am;				eclass = ExprClass.Value;			}			public override Expression DoResolve (EmitContext ec)			{				return this;

⌨️ 快捷键说明

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