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

📄 attribute.cs

📁 C#编译器源代码。Micorsoft开放源代码
💻 CS
📖 第 1 页 / 共 4 页
字号:
//// attribute.cs: Attribute Handler//// Author: Ravi Pratap (ravi@ximian.com)//         Marek Safar (marek.safar@seznam.cz)//// Licensed under the terms of the GNU GPL//// (C) 2001 Ximian, Inc (http://www.ximian.com)////using System;using System.Diagnostics;using System.Collections;using System.Collections.Specialized;using System.Reflection;using System.Reflection.Emit;using System.Runtime.InteropServices;using System.Runtime.CompilerServices;using System.Security; using System.Security.Permissions;using System.Text;using System.IO;namespace Mono.CSharp {	/// <summary>	///   Base class for objects that can have Attributes applied to them.	/// </summary>	public abstract class Attributable {		/// <summary>		///   Attributes for this type		/// </summary> 		Attributes attributes;		public Attributable (Attributes attrs)		{			attributes = attrs;		}		public Attributes OptAttributes 		{			get {				return attributes;			}			set {				attributes = value;			}		}		/// <summary>		/// Use member-specific procedure to apply attribute @a in @cb to the entity being built in @builder		/// </summary>		public abstract void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb);		/// <summary>		/// Returns one AttributeTarget for this element.		/// </summary>		public abstract AttributeTargets AttributeTargets { get; }		public abstract bool IsClsCompliaceRequired (DeclSpace ds);		/// <summary>		/// Gets list of valid attribute targets for explicit target declaration.		/// The first array item is default target. Don't break this rule.		/// </summary>		public abstract string[] ValidAttributeTargets { get; }	};	public class Attribute {		public readonly string ExplicitTarget;		public AttributeTargets Target;		// TODO: remove this member		public readonly string    Name;		public readonly Expression LeftExpr;		public readonly string Identifier;		public readonly ArrayList Arguments;		public readonly Location Location;		public Type Type;		bool resolve_error;		readonly bool nameEscaped;		static AttributeUsageAttribute DefaultUsageAttribute = new AttributeUsageAttribute (AttributeTargets.All);		static Assembly orig_sec_assembly;		// non-null if named args present after Resolve () is called		PropertyInfo [] prop_info_arr;		FieldInfo [] field_info_arr;		object [] field_values_arr;		object [] prop_values_arr;		object [] pos_values;		static PtrHashtable usage_attr_cache = new PtrHashtable ();				public Attribute (string target, Expression left_expr, string identifier, ArrayList args, Location loc, bool nameEscaped)		{			LeftExpr = left_expr;			Identifier = identifier;			Name = LeftExpr == null ? identifier : LeftExpr + "." + identifier;			Arguments = args;			Location = loc;			ExplicitTarget = target;			this.nameEscaped = nameEscaped;		}		void Error_InvalidNamedArgument (string name)		{			Report.Error (617, Location, "`{0}' is not a valid named attribute argument. Named attribute arguments " +				      "must be fields which are not readonly, static, const or read-write properties which are " +				      "public and not static",			      name);		}		void Error_InvalidNamedAgrumentType (string name)		{			Report.Error (655, Location, "`{0}' is not a valid named attribute argument because it is not a valid " +				      "attribute parameter type", name);		}		static void Error_AttributeArgumentNotValid (string extra, Location loc)		{			Report.Error (182, loc,				      "An attribute argument must be a constant expression, typeof " +				      "expression or array creation expression" + extra);		}		static void Error_AttributeArgumentNotValid (Location loc)		{			Error_AttributeArgumentNotValid ("", loc);		}				/// <summary>		/// This is rather hack. We report many emit attribute error with same error to be compatible with		/// csc. But because csc has to report them this way because error came from ilasm we needn't.		/// </summary>		public void Error_AttributeEmitError (string inner)		{			Report.Error (647, Location, "Error during emitting `{0}' attribute. The reason is `{1}'",				      TypeManager.CSharpName (Type), inner);		}		public void Error_InvalidSecurityParent ()		{			Error_AttributeEmitError ("it is attached to invalid parent");		}		protected virtual FullNamedExpression ResolveAsTypeTerminal (Expression expr, EmitContext ec, bool silent)		{			return expr.ResolveAsTypeTerminal (ec, silent);		}		protected virtual FullNamedExpression ResolveAsTypeStep (Expression expr, EmitContext ec, bool silent)		{			return expr.ResolveAsTypeStep (ec, silent);		}		Type ResolvePossibleAttributeType (EmitContext ec, string name, bool silent, ref bool is_attr)		{			FullNamedExpression fn;			if (LeftExpr == null) {				fn = ResolveAsTypeTerminal (new SimpleName (name, Location), ec, silent);			} else {				fn = ResolveAsTypeStep (LeftExpr, ec, silent);				if (fn == null)					return null;				fn = new MemberAccess (fn, name, Location).ResolveAsTypeTerminal (ec, silent);			}			TypeExpr te = fn as TypeExpr;			if (te == null)				return null;			Type t = te.Type;			if (t.IsSubclassOf (TypeManager.attribute_type)) {				is_attr = true;			} else if (!silent) {				Report.SymbolRelatedToPreviousError (t);				Report.Error (616, Location, "`{0}': is not an attribute class", TypeManager.CSharpName (t));			}			return t;		}		/// <summary>		///   Tries to resolve the type of the attribute. Flags an error if it can't, and complain is true.		/// </summary>		void ResolveAttributeType (EmitContext ec)		{			bool t1_is_attr = false;			Type t1 = ResolvePossibleAttributeType (ec, Identifier, true, ref t1_is_attr);			bool t2_is_attr = false;			Type t2 = nameEscaped ? null :				ResolvePossibleAttributeType (ec, Identifier + "Attribute", true, ref t2_is_attr);			if (t1_is_attr && t2_is_attr) {				Report.Error (1614, Location, "`{0}' is ambiguous between `{0}' and `{0}Attribute'. " +					      "Use either `@{0}' or `{0}Attribute'", GetSignatureForError ());				resolve_error = true;				return;			}			if (t1_is_attr) {				Type = t1;				return;			}			if (t2_is_attr) {				Type = t2;				return;			}			if (t1 == null && t2 == null)				ResolvePossibleAttributeType (ec, Identifier, false, ref t1_is_attr);			if (t1 != null)				ResolvePossibleAttributeType (ec, Identifier, false, ref t1_is_attr);			if (t2 != null)				ResolvePossibleAttributeType (ec, Identifier + "Attribute", false, ref t2_is_attr);			resolve_error = true;		}		public virtual Type ResolveType (EmitContext ec)		{			if (Type == null && !resolve_error)				ResolveAttributeType (ec);			return Type;		}		public string GetSignatureForError ()		{			return LeftExpr == null ? Identifier : LeftExpr.GetSignatureForError () + "." + Identifier;		}		//		// Given an expression, if the expression is a valid attribute-argument-expression		// returns an object that can be used to encode it, or null on failure.		//		public static bool GetAttributeArgumentExpression (Expression e, Location loc, Type arg_type, out object result)		{			Constant constant = e as Constant;			if (constant != null) {				constant = constant.ToType (arg_type, loc);				if (constant == null) {					result = null;					return false;				}				result = constant.GetTypedValue ();				return true;			} else if (e is TypeOf) {				result = ((TypeOf) e).TypeArg;				return true;			} else if (e is ArrayCreation){				result =  ((ArrayCreation) e).EncodeAsAttribute ();				if (result != null)					return true;			} else if (e is EmptyCast) {				Expression child = ((EmptyCast)e).Child;				return GetAttributeArgumentExpression (child, loc, child.Type, out result);			} else if (e is As) {				As as_e = (As) e;				return GetAttributeArgumentExpression (as_e.Expr, loc, as_e.ProbeType.Type, out result);			}			result = null;			Error_AttributeArgumentNotValid (loc);			return false;		}		bool IsValidArgumentType (Type t)		{			if (t.IsArray)				t = t.GetElementType ();			return TypeManager.IsPrimitiveType (t) ||				TypeManager.IsEnumType (t) ||				t == TypeManager.string_type ||				t == TypeManager.object_type ||				t == TypeManager.type_type;		}		// Cache for parameter-less attributes		static PtrHashtable att_cache = new PtrHashtable ();		public CustomAttributeBuilder Resolve (EmitContext ec)		{			if (resolve_error)				return null;			resolve_error = true;			if (Type == null) {				ResolveAttributeType (ec);				if (Type == null)					return null;			}			if (Type.IsAbstract) {				Report.Error (653, Location, "Cannot apply attribute class `{0}' because it is abstract", GetSignatureForError ());				return null;			}			ObsoleteAttribute obsolete_attr = AttributeTester.GetObsoleteAttribute (Type);			if (obsolete_attr != null) {				AttributeTester.Report_ObsoleteMessage (obsolete_attr, TypeManager.CSharpName (Type), Location);			}			if (Arguments == null) {				object o = att_cache [Type];				if (o != null) {					resolve_error = false;					return (CustomAttributeBuilder)o;				}			}			ConstructorInfo ctor = ResolveArguments (ec);			if (ctor == null)				return null;			CustomAttributeBuilder cb;			try {				if (prop_info_arr != null || field_info_arr != null) {					cb = new CustomAttributeBuilder (						ctor, pos_values,						prop_info_arr, prop_values_arr,						field_info_arr, field_values_arr);				} else {					cb = new CustomAttributeBuilder (						ctor, pos_values);					if (pos_values.Length == 0)						att_cache.Add (Type, cb);				}			}			catch (Exception) {				Error_AttributeArgumentNotValid (Location);				return null;			}			resolve_error = false;			return cb;		}		protected virtual ConstructorInfo ResolveArguments (EmitContext ec)		{			// Now we extract the positional and named arguments						ArrayList pos_args = null;			ArrayList named_args = null;			int pos_arg_count = 0;			int named_arg_count = 0;						if (Arguments != null) {				pos_args = (ArrayList) Arguments [0];				if (pos_args != null)					pos_arg_count = pos_args.Count;				if (Arguments.Count > 1) {					named_args = (ArrayList) Arguments [1];					named_arg_count = named_args.Count;				}			}			pos_values = new object [pos_arg_count];			//			// First process positional arguments 			//			int i;			for (i = 0; i < pos_arg_count; i++) {				Argument a = (Argument) pos_args [i];				Expression e;				if (!a.Resolve (ec, Location))					return null;				e = a.Expr;				object val;				if (!GetAttributeArgumentExpression (e, Location, a.Type, out val))					return null;				pos_values [i] = val;				if (i == 0 && Type == TypeManager.attribute_usage_type && (int)val == 0) {					Report.Error (591, Location, "Invalid value for argument to 'System.AttributeUsage' attribute");					return null;				}			}			//			// Now process named arguments			//			ArrayList field_infos = null;			ArrayList prop_infos  = null;			ArrayList field_values = null;			ArrayList prop_values = null;			Hashtable seen_names = null;			if (named_arg_count > 0) {				field_infos = new ArrayList ();				prop_infos  = new ArrayList ();				field_values = new ArrayList ();				prop_values = new ArrayList ();				seen_names = new Hashtable();			}						for (i = 0; i < named_arg_count; i++) {				DictionaryEntry de = (DictionaryEntry) named_args [i];				string member_name = (string) de.Key;				Argument a  = (Argument) de.Value;				Expression e;				if (seen_names.Contains(member_name)) {					Report.Error(643, Location, "'" + member_name + "' duplicate named attribute argument");					return null;				}								seen_names.Add(member_name, 1);								if (!a.Resolve (ec, Location))					return null;				Expression member = Expression.MemberLookup (					ec, Type, member_name,					MemberTypes.Field | MemberTypes.Property,					BindingFlags.Public | BindingFlags.Instance,					Location);				if (member == null) {					member = Expression.MemberLookup (ec, Type, member_name,						MemberTypes.Field | MemberTypes.Property, BindingFlags.NonPublic | BindingFlags.Instance,						Location);					if (member != null) {						Expression.ErrorIsInaccesible (Location, member.GetSignatureForError ());						return null;					}				}				if (member == null){					Report.Error (117, Location, "`{0}' does not contain a definition for `{1}'",						      Type, member_name);					return null;				}								if (!(member is PropertyExpr || member is FieldExpr)) {					Error_InvalidNamedArgument (member_name);					return null;				}

⌨️ 快捷键说明

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