2 // attribute.cs: Attribute Handler
\r
4 // Author: Ravi Pratap (ravi@ximian.com)
\r
6 // Licensed under the terms of the GNU GPL
\r
8 // (C) 2001 Ximian, Inc (http://www.ximian.com)
\r
13 using System.Collections;
\r
14 using System.Reflection;
\r
15 using System.Reflection.Emit;
\r
19 public class Attribute {
\r
21 public readonly string Name;
\r
22 public readonly ArrayList Arguments;
\r
26 public Attribute (string name, ArrayList args, Location loc)
\r
33 void error617 (string name)
\r
35 Report.Error (617, Location, "'" + name + "' is not a valid named attribute " +
\r
36 "argument. Named attribute arguments must be fields which are not " +
\r
37 "readonly, static or const, or properties with a set accessor which "+
\r
43 Report.Error (182, Location,
\r
44 "An attribute argument must be a constant expression, typeof " +
\r
45 "expression or array creation expression");
\r
48 public CustomAttributeBuilder Resolve (EmitContext ec)
\r
52 if (Name.IndexOf ("Attribute") == -1)
\r
53 name = Name + "Attribute";
\r
54 else if (Name.LastIndexOf ("Attribute") == 0)
\r
55 name = Name + "Attribute";
\r
57 Type attribute_type = ec.TypeContainer.LookupType (name, false);
\r
59 if (attribute_type == null) {
\r
60 Report.Error (246, Location, "Could not find attribute '" + Name + "' (are you" +
\r
61 " missing a using directive or an assembly reference ?)");
\r
65 // Now we extract the positional and named arguments
\r
67 ArrayList pos_args = new ArrayList ();
\r
68 ArrayList named_args = new ArrayList ();
\r
70 if (Arguments != null) {
\r
71 pos_args = (ArrayList) Arguments [0];
\r
72 if (Arguments.Count > 1)
\r
73 named_args = (ArrayList) Arguments [1];
\r
76 object [] pos_values = new object [pos_args.Count];
\r
79 // First process positional arguments
\r
83 for (i = 0; i < pos_args.Count; i++) {
\r
85 Argument a = (Argument) pos_args [i];
\r
87 if (!a.Resolve (ec))
\r
90 Expression e = Expression.Reduce (ec, a.Expr);
\r
93 pos_values [i] = ((Literal) e).GetValue ();
\r
101 // Now process named arguments
\r
104 ArrayList field_infos = new ArrayList ();
\r
105 ArrayList prop_infos = new ArrayList ();
\r
106 ArrayList field_values = new ArrayList ();
\r
107 ArrayList prop_values = new ArrayList ();
\r
109 for (i = 0; i < named_args.Count; i++) {
\r
111 DictionaryEntry de = (DictionaryEntry) named_args [i];
\r
113 string member_name = (string) de.Key;
\r
114 Argument a = (Argument) de.Value;
\r
116 if (!a.Resolve (ec))
\r
119 Expression member = Expression.MemberLookup (ec, attribute_type, member_name, false,
\r
120 MemberTypes.Field | MemberTypes.Property,
\r
121 BindingFlags.Public | BindingFlags.Instance,
\r
124 if (member == null || !(member is PropertyExpr || member is FieldExpr)) {
\r
125 error617 (member_name);
\r
129 if (member is PropertyExpr) {
\r
130 PropertyExpr pe = (PropertyExpr) member;
\r
131 PropertyInfo pi = pe.PropertyInfo;
\r
133 if (!pi.CanWrite) {
\r
134 error617 (member_name);
\r
138 Expression e = Expression.Reduce (ec, a.Expr);
\r
141 prop_values.Add (((Literal) e).GetValue ());
\r
147 prop_infos.Add (pi);
\r
149 } else if (member is FieldExpr) {
\r
150 FieldExpr fe = (FieldExpr) member;
\r
151 FieldInfo fi = fe.FieldInfo;
\r
153 if (fi.IsInitOnly) {
\r
154 error617 (member_name);
\r
158 Expression e = Expression.Reduce (ec, a.Expr);
\r
161 field_values.Add (((Literal) e).GetValue ());
\r
167 field_infos.Add (fi);
\r
171 Expression mg = Expression.MemberLookup (ec, attribute_type, ".ctor", false,
\r
172 MemberTypes.Constructor,
\r
173 BindingFlags.Public | BindingFlags.Instance,
\r
177 Report.Error (-6, Location, "Could not find a constructor for this argument list.");
\r
181 MethodBase constructor = Invocation.OverloadResolve (ec, (MethodGroupExpr) mg, pos_args, Location);
\r
183 if (constructor == null) {
\r
184 Report.Error (-6, Location, "Could not find a constructor for this argument list.");
\r
188 PropertyInfo [] prop_info_arr = new PropertyInfo [prop_infos.Count];
\r
189 FieldInfo [] field_info_arr = new FieldInfo [field_infos.Count];
\r
190 object [] field_values_arr = new object [field_values.Count];
\r
191 object [] prop_values_arr = new object [prop_values.Count];
\r
193 field_infos.CopyTo (field_info_arr, 0);
\r
194 field_values.CopyTo (field_values_arr, 0);
\r
196 prop_values.CopyTo (prop_values_arr, 0);
\r
197 prop_infos.CopyTo (prop_info_arr, 0);
\r
199 CustomAttributeBuilder cb = new CustomAttributeBuilder ((ConstructorInfo) constructor, pos_values,
\r
200 prop_info_arr, prop_values_arr,
\r
201 field_info_arr, field_values_arr);
\r
208 public class AttributeSection {
\r
210 public readonly string Target;
\r
211 public readonly ArrayList Attributes;
\r
213 public AttributeSection (string target, ArrayList attrs)
\r
216 Attributes = attrs;
\r
221 public class Attributes {
\r
223 public ArrayList AttributeSections;
\r
225 public Attributes (AttributeSection a)
\r
227 AttributeSections = new ArrayList ();
\r
228 AttributeSections.Add (a);
\r
232 public void AddAttribute (AttributeSection a)
\r
235 AttributeSections.Add (a);
\r