📄 attribute.cs
字号:
} } PermissionSet ps = (PermissionSet)permissions [action]; if (ps == null) { if (sa is PermissionSetAttribute) ps = new PermissionSet (sa.Unrestricted ? PermissionState.Unrestricted : PermissionState.None); else ps = new PermissionSet (PermissionState.None); permissions.Add (action, ps); } else if (!ps.IsUnrestricted () && (sa is PermissionSetAttribute) && sa.Unrestricted) { ps = ps.Union (new PermissionSet (PermissionState.Unrestricted)); permissions [action] = ps; } ps.AddPermission (perm); } object GetValue (object value) { if (value is EnumConstant) return ((EnumConstant) value).GetValue (); else return value; } public object GetPropertyValue (string name) { if (prop_info_arr == null) return null; for (int i = 0; i < prop_info_arr.Length; ++i) { if (prop_info_arr [i].Name == name) return prop_values_arr [i]; } return null; } object GetFieldValue (string name) { int i; if (field_info_arr == null) return null; i = 0; foreach (FieldInfo fi in field_info_arr) { if (fi.Name == name) return GetValue (field_values_arr [i]); i++; } return null; } // // Theoretically, we can get rid of this, since FieldBuilder.SetCustomAttribute() // and ParameterBuilder.SetCustomAttribute() are supposed to handle this attribute. // However, we can't, since it appears that the .NET 1.1 SRE hangs when given a MarshalAsAttribute. // public UnmanagedMarshal GetMarshal (Attributable attr) { UnmanagedType UnmanagedType; if (!RootContext.StdLib || pos_values [0].GetType () != typeof (UnmanagedType)) UnmanagedType = (UnmanagedType) System.Enum.ToObject (typeof (UnmanagedType), pos_values [0]); else UnmanagedType = (UnmanagedType) pos_values [0]; object value = GetFieldValue ("SizeParamIndex"); if (value != null && UnmanagedType != UnmanagedType.LPArray) { Error_AttributeEmitError ("SizeParamIndex field is not valid for the specified unmanaged type"); return null; } object o = GetFieldValue ("ArraySubType"); UnmanagedType array_sub_type = o == null ? (UnmanagedType) 0x50 /* NATIVE_MAX */ : (UnmanagedType) o; switch (UnmanagedType) { case UnmanagedType.CustomMarshaler: { MethodInfo define_custom = typeof (UnmanagedMarshal).GetMethod ("DefineCustom", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (define_custom == null) { Report.RuntimeMissingSupport (Location, "set marshal info"); return null; } object [] args = new object [4]; args [0] = GetFieldValue ("MarshalTypeRef"); args [1] = GetFieldValue ("MarshalCookie"); args [2] = GetFieldValue ("MarshalType"); args [3] = Guid.Empty; return (UnmanagedMarshal) define_custom.Invoke (null, args); } case UnmanagedType.LPArray: { object size_const = GetFieldValue ("SizeConst"); object size_param_index = GetFieldValue ("SizeParamIndex"); if ((size_const != null) || (size_param_index != null)) { MethodInfo define_array = typeof (UnmanagedMarshal).GetMethod ("DefineLPArrayInternal", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (define_array == null) { Report.RuntimeMissingSupport (Location, "set marshal info"); return null; } object [] args = new object [3]; args [0] = array_sub_type; args [1] = size_const == null ? -1 : size_const; args [2] = size_param_index == null ? -1 : size_param_index; return (UnmanagedMarshal) define_array.Invoke (null, args); } else return UnmanagedMarshal.DefineLPArray (array_sub_type); } case UnmanagedType.SafeArray: return UnmanagedMarshal.DefineSafeArray (array_sub_type); case UnmanagedType.ByValArray: FieldMember fm = attr as FieldMember; if (fm == null) { Error_AttributeEmitError ("Specified unmanaged type is only valid on fields"); return null; } return UnmanagedMarshal.DefineByValArray ((int) GetFieldValue ("SizeConst")); case UnmanagedType.ByValTStr: return UnmanagedMarshal.DefineByValTStr ((int) GetFieldValue ("SizeConst")); default: return UnmanagedMarshal.DefineUnmanagedMarshal (UnmanagedType); } } public CharSet GetCharSetValue () { return (CharSet)System.Enum.Parse (typeof (CharSet), pos_values [0].ToString ()); } public MethodImplOptions GetMethodImplOptions () { if (pos_values [0].GetType () != typeof (MethodImplOptions)) return (MethodImplOptions)System.Enum.ToObject (typeof (MethodImplOptions), pos_values [0]); return (MethodImplOptions)pos_values [0]; } public LayoutKind GetLayoutKindValue () { if (!RootContext.StdLib || pos_values [0].GetType () != typeof (LayoutKind)) return (LayoutKind)System.Enum.ToObject (typeof (LayoutKind), pos_values [0]); return (LayoutKind)pos_values [0]; } /// <summary> /// Emit attribute for Attributable symbol /// </summary> public void Emit (EmitContext ec, Attributable ias, ListDictionary emitted_attr) { CustomAttributeBuilder cb = Resolve (ec); if (cb == null) return; AttributeUsageAttribute usage_attr = GetAttributeUsage (ec); if ((usage_attr.ValidOn & Target) == 0) { Report.Error (592, Location, "Attribute `{0}' is not valid on this declaration type. " + "It is valid on `{1}' declarations only", GetSignatureForError (), GetValidTargets ()); return; } try { ias.ApplyAttributeBuilder (this, cb); } catch (Exception e) { Error_AttributeEmitError (e.Message); return; } if (!usage_attr.AllowMultiple) { ArrayList emitted_targets = (ArrayList)emitted_attr [Type]; if (emitted_targets == null) { emitted_targets = new ArrayList (); emitted_attr.Add (Type, emitted_targets); } else if (emitted_targets.Contains (Target)) { Report.Error (579, Location, "Duplicate `{0}' attribute", GetSignatureForError ()); return; } emitted_targets.Add (Target); } if (!RootContext.VerifyClsCompliance) return; // Here we are testing attribute arguments for array usage (error 3016) if (ias.IsClsCompliaceRequired (ec.DeclSpace)) { if (Arguments == null) return; ArrayList pos_args = (ArrayList) Arguments [0]; if (pos_args != null) { foreach (Argument arg in pos_args) { // Type is undefined (was error 246) if (arg.Type == null) return; if (arg.Type.IsArray) { Report.Error (3016, Location, "Arrays as attribute arguments are not CLS-compliant"); return; } } } if (Arguments.Count < 2) return; ArrayList named_args = (ArrayList) Arguments [1]; foreach (DictionaryEntry de in named_args) { Argument arg = (Argument) de.Value; // Type is undefined (was error 246) if (arg.Type == null) return; if (arg.Type.IsArray) { Report.Error (3016, Location, "Arrays as attribute arguments are not CLS-compliant"); return; } } } } public MethodBuilder DefinePInvokeMethod (EmitContext ec, TypeBuilder builder, string name, MethodAttributes flags, Type ret_type, Type [] param_types) { if (pos_values == null) // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args. // But because a lot of attribute class code must be rewritten will be better to wait... Resolve (ec); if (resolve_error) return null; string dll_name = (string)pos_values [0]; // Default settings CallingConvention cc = CallingConvention.Winapi; CharSet charset = CodeGen.Module.DefaultCharSet; bool preserve_sig = true; string entry_point = name; bool best_fit_mapping = false; bool throw_on_unmappable = false; bool exact_spelling = false; bool set_last_error = false; bool best_fit_mapping_set = false; bool throw_on_unmappable_set = false; bool exact_spelling_set = false; bool set_last_error_set = false; MethodInfo set_best_fit = null; MethodInfo set_throw_on = null; MethodInfo set_exact_spelling = null; MethodInfo set_set_last_error = null; if (field_info_arr != null) { for (int i = 0; i < field_info_arr.Length; i++) { switch (field_info_arr [i].Name) { case "BestFitMapping": best_fit_mapping = (bool) field_values_arr [i]; best_fit_mapping_set = true; break; case "CallingConvention": cc = (CallingConvention) field_values_arr [i]; break; case "CharSet": charset = (CharSet) field_values_arr [i]; break; case "EntryPoint": entry_point = (string) field_values_arr [i]; break; case "ExactSpelling": exact_spelling = (bool) field_values_arr [i]; exact_spelling_set = true; break; case "PreserveSig": preserve_sig = (bool) field_values_arr [i]; break; case "SetLastError": set_last_error = (bool) field_values_arr [i]; set_last_error_set = true; break; case "ThrowOnUnmappableChar": throw_on_unmappable = (bool) field_values_arr [i]; throw_on_unmappable_set = true; break; default: throw new InternalErrorException (field_info_arr [i].ToString ()); } } } if (throw_on_unmappable_set || best_fit_mapping_set || exact_spelling_set || set_last_error_set) { set_best_fit = typeof (MethodBuilder). GetMethod ("set_BestFitMapping", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); set_throw_on = typeof (MethodBuilder). GetMethod ("set_ThrowOnUnmappableChar", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); set_exact_spelling = typeof (MethodBuilder). GetMethod ("set_ExactSpelling", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); set_set_last_error = typeof (MethodBuilder). GetMethod ("set_SetLastError", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if ((set_best_fit == null) || (set_throw_on == null) || (set_exact_spelling == null) || (set_set_last_error == null)) { Report.Error (-1, Location, "The ThrowOnUnmappableChar, BestFitMapping, SetLastError, " + "and ExactSpelling attributes can only be emitted when running on the mono runtime."); return null; } } try { MethodBuilder mb = builder.DefinePInvokeMethod ( name, dll_name, entry_point, flags | MethodAttributes.HideBySig | MethodAttributes.PinvokeImpl, CallingConventions.Standard, ret_type, param_types, cc, charset); if (preserve_sig) mb.SetImplementationFlags (MethodImplAttributes.PreserveSig); if (throw_on_unmappable_set) set_throw_on.Invoke (mb, 0, null, new object [] { throw_on_unmappable }, null); if (best_fit_mapping_set) set_best_fit.Invoke (mb, 0, null, new object [] { best_fit_mapping }, null); if (exact_spelling_set) set_exact_spelling.Invoke (mb, 0, null, new object [] { exact_spelling }, null); if (set_last_error_set) set_set_last_error.Invoke (mb, 0, null, new object [] { set_last_error }, null); return mb; } catch (ArgumentException e) { Error_AttributeEmitError (e.Message); return null; } } private Expression GetValue () { if ((Arguments == null) || (Arguments.Count < 1)) return null; ArrayList al = (ArrayList) Arguments [0]; if ((al == null) || (al.Count < 1)) return null; Argument arg = (Argument) al [0]; if ((arg == null) || (arg.Expr == null)) return null; return arg.Expr; } public string GetString () { Expression e = GetValue (); if (e is StringLiteral) return (e as StringLiteral).Value; return null; } public bool GetBoolean () { Expression e = GetValue (); if (e is BoolLiteral) return (e as BoolLiteral).Value; return false; } } /// <summary> /// For global attributes (assembly, module) we need special handling. /// Attributes can be located in the several files /// </summary> public class GlobalAttribute : Attribute { public readonly NamespaceEntry ns; public GlobalAttribute (TypeContainer container, string target, Expression left_expr, string identifier, ArrayList args, Location loc, bool nameEscaped): base (target, left_expr, identifier, args, loc, nameEscaped) { ns = container.NamespaceEntry; } void Enter () { // RootContext.Tree.Types has a single NamespaceEntry which gets overwritten // each time a new file is parsed. However, we need to use the NamespaceEntry // in effect where the attribute was used. Since code elsewhere cannot assume // that the NamespaceEntry is right, just overwrite it. // // Precondition: RootContext.Tree.Types == null if (RootContext.Tree.Types.NamespaceEntry != null) throw new InternalErrorException (Location + " non-null NamespaceEntry"); RootContext.Tree.Types.NamespaceEntry = ns; } void Leave () { RootContext.Tree.Types.NamespaceEntry = null; } protected override FullNamedExpression ResolveAsTypeStep (Expression expr, EmitContext ec, bool silent) { try { Enter (); return base.ResolveAsTypeStep (expr, ec, silent); } finally { Leave (); } } protected override FullNamedExpression ResolveAsTypeTerminal (Expression expr, EmitContext ec, bool silent) { try { Enter (); return base.ResolveAsTypeTerminal (expr, ec, silent); } finally { Leave (); } } protected override ConstructorInfo ResolveArguments (EmitContext ec) { try { Enter (); return base.ResolveArguments (ec); } finally { Leave (); } } } public class Attributes { public ArrayList Attrs; public Attributes (Attribute a) { Attrs = new ArrayList (); Attrs.Add (a); } public Attributes (ArrayList attrs) { Attrs = attrs; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -