📄 attribute.cs
字号:
e = a.Expr; if (member is PropertyExpr) { PropertyExpr pe = (PropertyExpr) member; PropertyInfo pi = pe.PropertyInfo; if (!pi.CanWrite || !pi.CanRead) { Report.SymbolRelatedToPreviousError (pi); Error_InvalidNamedArgument (member_name); return null; } if (!IsValidArgumentType (pi.PropertyType)) { Report.SymbolRelatedToPreviousError (pi); Error_InvalidNamedAgrumentType (member_name); return null; } object value; if (!GetAttributeArgumentExpression (e, Location, pi.PropertyType, out value)) return null; prop_values.Add (value); prop_infos.Add (pi); } else if (member is FieldExpr) { FieldExpr fe = (FieldExpr) member; FieldInfo fi = fe.FieldInfo; if (fi.IsInitOnly) { Error_InvalidNamedArgument (member_name); return null; } if (!IsValidArgumentType (fi.FieldType)) { Report.SymbolRelatedToPreviousError (fi); Error_InvalidNamedAgrumentType (member_name); return null; } object value; if (!GetAttributeArgumentExpression (e, Location, fi.FieldType, out value)) return null; field_values.Add (value); field_infos.Add (fi); } } Expression mg = Expression.MemberLookup ( ec, Type, ".ctor", MemberTypes.Constructor, BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly, Location); MethodBase constructor = Invocation.OverloadResolve ( ec, (MethodGroupExpr) mg, pos_args, false, Location); if (constructor == null) { return null; } // Here we do the checks which should be done by corlib or by runtime. // However Zoltan doesn't like it and every Mono compiler has to do it again. if (Type == TypeManager.guid_attr_type) { try { new Guid ((string)pos_values [0]); } catch (Exception e) { Error_AttributeEmitError (e.Message); return null; } } if (Type == TypeManager.methodimpl_attr_type && pos_values.Length == 1 && ((Argument)pos_args [0]).Type == TypeManager.short_type && !System.Enum.IsDefined (typeof (MethodImplOptions), pos_values [0])) { Error_AttributeEmitError ("Incorrect argument value."); return null; } // // Now we perform some checks on the positional args as they // cannot be null for a constructor which expects a parameter // of type object // ParameterData pd = TypeManager.GetParameterData (constructor); int last_real_param = pd.Count; if (pd.HasParams) { // When the params is not filled we need to put one if (last_real_param > pos_arg_count) { object [] new_pos_values = new object [pos_arg_count + 1]; pos_values.CopyTo (new_pos_values, 0); new_pos_values [pos_arg_count] = new object [] {} ; pos_values = new_pos_values; } last_real_param--; } for (int j = 0; j < pos_arg_count; ++j) { Argument a = (Argument) pos_args [j]; if (a.Expr is NullLiteral && pd.ParameterType (j) == TypeManager.object_type) { Error_AttributeArgumentNotValid (Location); return null; } object value = pos_values [j]; if (value != null && a.Type != value.GetType () && TypeManager.IsPrimitiveType (a.Type)) { bool fail; pos_values [j] = TypeManager.ChangeType (value, a.Type, out fail); if (fail) { // TODO: Can failed ? throw new NotImplementedException (); } } if (j < last_real_param) continue; if (j == last_real_param) { object [] array = new object [pos_arg_count - last_real_param]; array [0] = pos_values [j]; pos_values [j] = array; continue; } object [] params_array = (object []) pos_values [last_real_param]; params_array [j - last_real_param] = pos_values [j]; } // Adjust the size of the pos_values if it had params if (last_real_param != pos_arg_count) { object [] new_pos_values = new object [last_real_param + 1]; Array.Copy (pos_values, new_pos_values, last_real_param + 1); pos_values = new_pos_values; } if (named_arg_count > 0) { prop_info_arr = new PropertyInfo [prop_infos.Count]; field_info_arr = new FieldInfo [field_infos.Count]; field_values_arr = new object [field_values.Count]; prop_values_arr = new object [prop_values.Count]; field_infos.CopyTo (field_info_arr, 0); field_values.CopyTo (field_values_arr, 0); prop_values.CopyTo (prop_values_arr, 0); prop_infos.CopyTo (prop_info_arr, 0); } return (ConstructorInfo) constructor; } /// <summary> /// Get a string containing a list of valid targets for the attribute 'attr' /// </summary> public string GetValidTargets () { StringBuilder sb = new StringBuilder (); AttributeTargets targets = GetAttributeUsage (null).ValidOn; if ((targets & AttributeTargets.Assembly) != 0) sb.Append ("assembly, "); if ((targets & AttributeTargets.Module) != 0) sb.Append ("module, "); if ((targets & AttributeTargets.Class) != 0) sb.Append ("class, "); if ((targets & AttributeTargets.Struct) != 0) sb.Append ("struct, "); if ((targets & AttributeTargets.Enum) != 0) sb.Append ("enum, "); if ((targets & AttributeTargets.Constructor) != 0) sb.Append ("constructor, "); if ((targets & AttributeTargets.Method) != 0) sb.Append ("method, "); if ((targets & AttributeTargets.Property) != 0) sb.Append ("property, indexer, "); if ((targets & AttributeTargets.Field) != 0) sb.Append ("field, "); if ((targets & AttributeTargets.Event) != 0) sb.Append ("event, "); if ((targets & AttributeTargets.Interface) != 0) sb.Append ("interface, "); if ((targets & AttributeTargets.Parameter) != 0) sb.Append ("parameter, "); if ((targets & AttributeTargets.Delegate) != 0) sb.Append ("delegate, "); if ((targets & AttributeTargets.ReturnValue) != 0) sb.Append ("return, ");#if NET_2_0 if ((targets & AttributeTargets.GenericParameter) != 0) sb.Append ("type parameter, ");#endif return sb.Remove (sb.Length - 2, 2).ToString (); } /// <summary> /// Returns AttributeUsage attribute for this type /// </summary> AttributeUsageAttribute GetAttributeUsage (EmitContext ec) { AttributeUsageAttribute ua = usage_attr_cache [Type] as AttributeUsageAttribute; if (ua != null) return ua; Class attr_class = TypeManager.LookupClass (Type); if (attr_class == null) { object[] usage_attr = Type.GetCustomAttributes (TypeManager.attribute_usage_type, true); ua = (AttributeUsageAttribute)usage_attr [0]; usage_attr_cache.Add (Type, ua); return ua; } Attribute a = attr_class.OptAttributes == null ? null : attr_class.OptAttributes.Search (TypeManager.attribute_usage_type, attr_class.EmitContext); ua = a == null ? DefaultUsageAttribute : a.GetAttributeUsageAttribute (attr_class.EmitContext); usage_attr_cache.Add (Type, ua); return ua; } AttributeUsageAttribute GetAttributeUsageAttribute (EmitContext ec) { 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 DefaultUsageAttribute; AttributeUsageAttribute usage_attribute = new AttributeUsageAttribute ((AttributeTargets)pos_values [0]); object field = GetPropertyValue ("AllowMultiple"); if (field != null) usage_attribute.AllowMultiple = (bool)field; field = GetPropertyValue ("Inherited"); if (field != null) usage_attribute.Inherited = (bool)field; return usage_attribute; } /// <summary> /// Returns custom name of indexer /// </summary> public string GetIndexerAttributeValue (EmitContext ec) { 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; return pos_values [0] as string; } /// <summary> /// Returns condition of ConditionalAttribute /// </summary> public string GetConditionalAttributeValue (EmitContext ec) { 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; return (string)pos_values [0]; } /// <summary> /// Creates the instance of ObsoleteAttribute from this attribute instance /// </summary> public ObsoleteAttribute GetObsoleteAttribute (EmitContext ec) { 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; if (pos_values == null || pos_values.Length == 0) return new ObsoleteAttribute (); if (pos_values.Length == 1) return new ObsoleteAttribute ((string)pos_values [0]); return new ObsoleteAttribute ((string)pos_values [0], (bool)pos_values [1]); } /// <summary> /// Returns value of CLSCompliantAttribute contructor parameter but because the method can be called /// before ApplyAttribute. We need to resolve the arguments. /// This situation occurs when class deps is differs from Emit order. /// </summary> public bool GetClsCompliantAttributeValue (EmitContext ec) { 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 false; return (bool)pos_values [0]; } public Type GetCoClassAttributeValue (EmitContext ec) { if (pos_values == null) Resolve (ec); if (resolve_error) return null; return (Type)pos_values [0]; } /// <summary> /// Tests permitted SecurityAction for assembly or other types /// </summary> public bool CheckSecurityActionValidity (bool for_assembly) { SecurityAction action = GetSecurityActionValue (); if ((action == SecurityAction.RequestMinimum || action == SecurityAction.RequestOptional || action == SecurityAction.RequestRefuse) && for_assembly) return true; if (!for_assembly) { if (action < SecurityAction.Demand || action > SecurityAction.InheritanceDemand) { Error_AttributeEmitError ("SecurityAction is out of range"); return false; } if ((action != SecurityAction.RequestMinimum && action != SecurityAction.RequestOptional && action != SecurityAction.RequestRefuse) && !for_assembly) return true; } Error_AttributeEmitError (String.Concat ("SecurityAction '", action, "' is not valid for this declaration")); return false; } System.Security.Permissions.SecurityAction GetSecurityActionValue () { return (SecurityAction)pos_values [0]; } /// <summary> /// Creates instance of SecurityAttribute class and add result of CreatePermission method to permission table. /// </summary> /// <returns></returns> public void ExtractSecurityPermissionSet (ListDictionary permissions) { Type orig_assembly_type = null; if (TypeManager.LookupDeclSpace (Type) != null) { if (!RootContext.StdLib) { orig_assembly_type = Type.GetType (Type.FullName); } else { string orig_version_path = Environment.GetEnvironmentVariable ("__SECURITY_BOOTSTRAP_DB"); if (orig_version_path == null) { Error_AttributeEmitError ("security custom attributes can not be referenced from defining assembly"); return; } if (orig_sec_assembly == null) { string file = Path.Combine (orig_version_path, Driver.OutputFile); orig_sec_assembly = Assembly.LoadFile (file); } orig_assembly_type = orig_sec_assembly.GetType (Type.FullName, true); if (orig_assembly_type == null) { Report.Warning (-112, 1, Location, "Self-referenced security attribute `{0}' " + "was not found in previous version of assembly"); return; } } } SecurityAttribute sa; // For all non-selfreferencing security attributes we can avoid all hacks if (orig_assembly_type == null) { sa = (SecurityAttribute) Activator.CreateInstance (Type, pos_values); if (prop_info_arr != null) { for (int i = 0; i < prop_info_arr.Length; ++i) { PropertyInfo pi = prop_info_arr [i]; pi.SetValue (sa, prop_values_arr [i], null); } } } else { // HACK: All security attributes have same ctor syntax sa = (SecurityAttribute) Activator.CreateInstance (orig_assembly_type, new object[] { GetSecurityActionValue () } ); // All types are from newly created assembly but for invocation with old one we need to convert them if (prop_info_arr != null) { for (int i = 0; i < prop_info_arr.Length; ++i) { PropertyInfo emited_pi = prop_info_arr [i]; PropertyInfo pi = orig_assembly_type.GetProperty (emited_pi.Name, emited_pi.PropertyType); object old_instance = pi.PropertyType.IsEnum ? System.Enum.ToObject (pi.PropertyType, prop_values_arr [i]) : prop_values_arr [i]; pi.SetValue (sa, old_instance, null); } } } IPermission perm; perm = sa.CreatePermission (); SecurityAction action = GetSecurityActionValue (); // IS is correct because for corlib we are using an instance from old corlib if (!(perm is System.Security.CodeAccessPermission)) { switch (action) { case SecurityAction.Demand: action = (SecurityAction)13; break; case SecurityAction.LinkDemand: action = (SecurityAction)14; break; case SecurityAction.InheritanceDemand: action = (SecurityAction)15; break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -