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.Diagnostics;
\r
14 using System.Collections;
\r
15 using System.Reflection;
\r
16 using System.Reflection.Emit;
\r
17 using System.Runtime.InteropServices;
\r
18 using System.Runtime.CompilerServices;
\r
21 namespace Mono.CSharp {
\r
23 public class Attribute {
\r
24 public readonly string Name;
\r
25 public readonly ArrayList Arguments;
\r
32 // The following are only meaningful when the attribute
\r
33 // being emitted is one of the builtin ones
\r
35 AttributeTargets Targets;
\r
39 bool UsageAttr = false;
\r
41 MethodImplOptions ImplOptions;
\r
42 UnmanagedType UnmanagedType;
\r
43 CustomAttributeBuilder cb;
\r
45 public Attribute (string name, ArrayList args, Location loc)
\r
52 void Error_InvalidNamedArgument (string name)
\r
54 Report.Error (617, Location, "'" + name + "' is not a valid named attribute " +
\r
55 "argument. Named attribute arguments must be fields which are not " +
\r
56 "readonly, static or const, or properties with a set accessor which "+
\r
60 void Error_AttributeArgumentNotValid ()
\r
62 Report.Error (182, Location,
\r
63 "An attribute argument must be a constant expression, typeof " +
\r
64 "expression or array creation expression");
\r
67 static void Error_AttributeConstructorMismatch (Location loc)
\r
71 "Could not find a constructor for this argument list.");
\r
74 private Type CheckAttributeType (EmitContext ec) {
\r
76 bool isattributeclass = true;
\r
78 t = RootContext.LookupType (ec.DeclSpace, Name, true, Location);
\r
80 isattributeclass = t.IsSubclassOf (TypeManager.attribute_type);
\r
81 if (isattributeclass)
\r
84 t = RootContext.LookupType (ec.DeclSpace, Name + "Attribute", true, Location);
\r
86 if (t.IsSubclassOf (TypeManager.attribute_type))
\r
89 if (!isattributeclass) {
\r
90 Report.Error (616, Location, "'" + Name + "': is not an attribute class");
\r
94 Report.Error (616, Location, "'" + Name + "Attribute': is not an attribute class");
\r
98 246, Location, "Could not find attribute '" + Name + "' (are you" +
\r
99 " missing a using directive or an assembly reference ?)");
\r
103 public Type ResolveType (EmitContext ec)
\r
105 Type = CheckAttributeType (ec);
\r
110 /// Validates the guid string
\r
112 bool ValidateGuid (string guid)
\r
118 Report.Error (647, Location, "Format of GUID is invalid: " + guid);
\r
123 public CustomAttributeBuilder Resolve (EmitContext ec)
\r
126 Type = CheckAttributeType (ec);
\r
130 bool MethodImplAttr = false;
\r
131 bool MarshalAsAttr = false;
\r
132 bool GuidAttr = false;
\r
135 bool DoCompares = true;
\r
136 if (Type == TypeManager.attribute_usage_type)
\r
138 else if (Type == TypeManager.methodimpl_attr_type)
\r
139 MethodImplAttr = true;
\r
140 else if (Type == TypeManager.marshal_as_attr_type)
\r
141 MarshalAsAttr = true;
\r
142 else if (Type == TypeManager.guid_attr_type)
\r
145 DoCompares = false;
\r
147 // Now we extract the positional and named arguments
\r
149 ArrayList pos_args = new ArrayList ();
\r
150 ArrayList named_args = new ArrayList ();
\r
151 int pos_arg_count = 0;
\r
153 if (Arguments != null) {
\r
154 pos_args = (ArrayList) Arguments [0];
\r
155 if (pos_args != null)
\r
156 pos_arg_count = pos_args.Count;
\r
157 if (Arguments.Count > 1)
\r
158 named_args = (ArrayList) Arguments [1];
\r
161 object [] pos_values = new object [pos_arg_count];
\r
164 // First process positional arguments
\r
168 for (i = 0; i < pos_arg_count; i++) {
\r
169 Argument a = (Argument) pos_args [i];
\r
172 if (!a.Resolve (ec, Location))
\r
177 if (e is Constant) {
\r
178 pos_values [i] = ((Constant) e).GetValue ();
\r
179 } else if (e is TypeOf) {
\r
180 pos_values [i] = ((TypeOf) e).TypeArg;
\r
182 Error_AttributeArgumentNotValid ();
\r
188 this.Targets = (AttributeTargets) pos_values [0];
\r
189 else if (MethodImplAttr)
\r
190 this.ImplOptions = (MethodImplOptions) pos_values [0];
\r
191 else if (GuidAttr){
\r
193 // we will later check the validity of the type
\r
195 if (pos_values [0] is string){
\r
196 if (!ValidateGuid ((string) pos_values [0]))
\r
200 } else if (MarshalAsAttr)
\r
201 this.UnmanagedType =
\r
202 (System.Runtime.InteropServices.UnmanagedType) pos_values [0];
\r
207 // Now process named arguments
\r
210 ArrayList field_infos = new ArrayList ();
\r
211 ArrayList prop_infos = new ArrayList ();
\r
212 ArrayList field_values = new ArrayList ();
\r
213 ArrayList prop_values = new ArrayList ();
\r
215 for (i = 0; i < named_args.Count; i++) {
\r
216 DictionaryEntry de = (DictionaryEntry) named_args [i];
\r
217 string member_name = (string) de.Key;
\r
218 Argument a = (Argument) de.Value;
\r
221 if (!a.Resolve (ec, Location))
\r
224 Expression member = Expression.MemberLookup (
\r
225 ec, Type, member_name,
\r
226 MemberTypes.Field | MemberTypes.Property,
\r
227 BindingFlags.Public | BindingFlags.Instance,
\r
230 if (member == null || !(member is PropertyExpr || member is FieldExpr)) {
\r
231 Error_InvalidNamedArgument (member_name);
\r
236 if (member is PropertyExpr) {
\r
237 PropertyExpr pe = (PropertyExpr) member;
\r
238 PropertyInfo pi = pe.PropertyInfo;
\r
240 if (!pi.CanWrite) {
\r
241 Error_InvalidNamedArgument (member_name);
\r
245 if (e is Constant) {
\r
246 object o = ((Constant) e).GetValue ();
\r
247 prop_values.Add (o);
\r
250 if (member_name == "AllowMultiple")
\r
251 this.AllowMultiple = (bool) o;
\r
252 if (member_name == "Inherited")
\r
253 this.Inherited = (bool) o;
\r
256 } else if (e is TypeOf) {
\r
257 prop_values.Add (((TypeOf) e).TypeArg);
\r
259 Error_AttributeArgumentNotValid ();
\r
263 prop_infos.Add (pi);
\r
265 } else if (member is FieldExpr) {
\r
266 FieldExpr fe = (FieldExpr) member;
\r
267 FieldInfo fi = fe.FieldInfo;
\r
269 if (fi.IsInitOnly) {
\r
270 Error_InvalidNamedArgument (member_name);
\r
275 // Handle charset here, and set the TypeAttributes
\r
277 if (e is Constant){
\r
278 object value = ((Constant) e).GetValue ();
\r
280 field_values.Add (value);
\r
281 } else if (e is TypeOf) {
\r
282 field_values.Add (((TypeOf) e).TypeArg);
\r
284 Error_AttributeArgumentNotValid ();
\r
288 field_infos.Add (fi);
\r
292 Expression mg = Expression.MemberLookup (
\r
293 ec, Type, ".ctor", MemberTypes.Constructor,
\r
294 BindingFlags.Public | BindingFlags.Instance, Location);
\r
297 Error_AttributeConstructorMismatch (Location);
\r
301 MethodBase constructor = Invocation.OverloadResolve (
\r
302 ec, (MethodGroupExpr) mg, pos_args, Location);
\r
304 if (constructor == null) {
\r
305 Error_AttributeConstructorMismatch (Location);
\r
310 // Now we perform some checks on the positional args as they
\r
311 // cannot be null for a constructor which expects a parameter
\r
315 ParameterData pd = Invocation.GetParameterData (constructor);
\r
317 for (int j = 0; j < pos_arg_count; ++j) {
\r
318 Argument a = (Argument) pos_args [j];
\r
320 if (a.Expr is NullLiteral && pd.ParameterType (j) == TypeManager.object_type) {
\r
321 Error_AttributeArgumentNotValid ();
\r
326 PropertyInfo [] prop_info_arr = new PropertyInfo [prop_infos.Count];
\r
327 FieldInfo [] field_info_arr = new FieldInfo [field_infos.Count];
\r
328 object [] field_values_arr = new object [field_values.Count];
\r
329 object [] prop_values_arr = new object [prop_values.Count];
\r
331 field_infos.CopyTo (field_info_arr, 0);
\r
332 field_values.CopyTo (field_values_arr, 0);
\r
334 prop_values.CopyTo (prop_values_arr, 0);
\r
335 prop_infos.CopyTo (prop_info_arr, 0);
\r
338 cb = new CustomAttributeBuilder (
\r
339 (ConstructorInfo) constructor, pos_values,
\r
340 prop_info_arr, prop_values_arr,
\r
341 field_info_arr, field_values_arr);
\r
343 } catch (NullReferenceException) {
\r
345 // Don't know what to do here
\r
348 -100, Location, "NullReferenceException while trying to create attribute. Something's wrong!");
\r
349 } catch (Exception e) {
\r
352 // using System.ComponentModel;
\r
353 // [DefaultValue (CollectionChangeAction.Add)]
\r
354 // class X { static void Main () {} }
\r
358 "The compiler can not encode this attribute in .NET due to\n" +
\r
359 "\ta bug in the .NET runtime. Try the Mono runtime.\nThe error was: " + e.Message);
\r
365 static string GetValidPlaces (Attribute attr)
\r
367 StringBuilder sb = new StringBuilder ();
\r
368 AttributeTargets targets = 0;
\r
370 TypeContainer a = TypeManager.LookupAttr (attr.Type);
\r
374 System.Attribute [] attrs = null;
\r
377 attrs = System.Attribute.GetCustomAttributes (attr.Type);
\r
380 Report.Error (-20, attr.Location, "Cannot find attribute type " + attr.Name +
\r
381 " (maybe you forgot to set the usage using the" +
\r
382 " AttributeUsage attribute ?).");
\r
386 foreach (System.Attribute tmp in attrs)
\r
387 if (tmp is AttributeUsageAttribute) {
\r
388 targets = ((AttributeUsageAttribute) tmp).ValidOn;
\r
392 targets = a.Targets;
\r
395 if ((targets & AttributeTargets.Assembly) != 0)
\r
396 sb.Append ("'assembly' ");
\r
398 if ((targets & AttributeTargets.Class) != 0)
\r
399 sb.Append ("'class' ");
\r
401 if ((targets & AttributeTargets.Constructor) != 0)
\r
402 sb.Append ("'constructor' ");
\r
404 if ((targets & AttributeTargets.Delegate) != 0)
\r
405 sb.Append ("'delegate' ");
\r
407 if ((targets & AttributeTargets.Enum) != 0)
\r
408 sb.Append ("'enum' ");
\r
410 if ((targets & AttributeTargets.Event) != 0)
\r
411 sb.Append ("'event' ");
\r
413 if ((targets & AttributeTargets.Field) != 0)
\r
414 sb.Append ("'field' ");
\r
416 if ((targets & AttributeTargets.Interface) != 0)
\r
417 sb.Append ("'interface' ");
\r
419 if ((targets & AttributeTargets.Method) != 0)
\r
420 sb.Append ("'method' ");
\r
422 if ((targets & AttributeTargets.Module) != 0)
\r
423 sb.Append ("'module' ");
\r
425 if ((targets & AttributeTargets.Parameter) != 0)
\r
426 sb.Append ("'parameter' ");
\r
428 if ((targets & AttributeTargets.Property) != 0)
\r
429 sb.Append ("'property' ");
\r
431 if ((targets & AttributeTargets.ReturnValue) != 0)
\r
432 sb.Append ("'return value' ");
\r
434 if ((targets & AttributeTargets.Struct) != 0)
\r
435 sb.Append ("'struct' ");
\r
437 return sb.ToString ();
\r
441 public static void Error_AttributeNotValidForElement (Attribute a, Location loc)
\r
444 592, loc, "Attribute '" + a.Name +
\r
445 "' is not valid on this declaration type. " +
\r
446 "It is valid on " + GetValidPlaces (a) + "declarations only.");
\r
449 public static bool CheckAttribute (Attribute a, object element)
\r
451 TypeContainer attr = TypeManager.LookupAttr (a.Type);
\r
452 AttributeTargets targets = 0;
\r
455 if (attr == null) {
\r
456 System.Attribute [] attrs = null;
\r
459 attrs = System.Attribute.GetCustomAttributes (a.Type);
\r
462 Report.Error (-20, a.Location, "Cannot find attribute type " + a.Name +
\r
463 " (maybe you forgot to set the usage using the" +
\r
464 " AttributeUsage attribute ?).");
\r
468 foreach (System.Attribute tmp in attrs)
\r
469 if (tmp is AttributeUsageAttribute)
\r
470 targets = ((AttributeUsageAttribute) tmp).ValidOn;
\r
472 targets = attr.Targets;
\r
474 if (element is Class) {
\r
475 if ((targets & AttributeTargets.Class) != 0)
\r
480 } else if (element is Struct) {
\r
481 if ((targets & AttributeTargets.Struct) != 0)
\r
485 } else if (element is Constructor) {
\r
486 if ((targets & AttributeTargets.Constructor) != 0)
\r
490 } else if (element is Delegate) {
\r
491 if ((targets & AttributeTargets.Delegate) != 0)
\r
495 } else if (element is Enum) {
\r
496 if ((targets & AttributeTargets.Enum) != 0)
\r
500 } else if (element is Event || element is InterfaceEvent) {
\r
501 if ((targets & AttributeTargets.Event) != 0)
\r
505 } else if (element is Field || element is FieldBuilder) {
\r
506 if ((targets & AttributeTargets.Field) != 0)
\r
510 } else if (element is Interface) {
\r
511 if ((targets & AttributeTargets.Interface) != 0)
\r
515 } else if (element is Method || element is Operator || element is InterfaceMethod || element is Accessor) {
\r
516 if ((targets & AttributeTargets.Method) != 0)
\r
520 } else if (element is ParameterBuilder) {
\r
521 if ((targets & AttributeTargets.Parameter) != 0)
\r
525 } else if (element is Property || element is Indexer ||
\r
526 element is InterfaceProperty || element is InterfaceIndexer) {
\r
527 if ((targets & AttributeTargets.Property) != 0)
\r
531 } else if (element is AssemblyBuilder){
\r
532 if ((targets & AttributeTargets.Assembly) != 0)
\r
542 // This method should be invoked to pull the IndexerName attribute from an
\r
543 // Indexer if it exists.
\r
545 public static string ScanForIndexerName (EmitContext ec, Attributes opt_attrs)
\r
547 if (opt_attrs == null)
\r
549 if (opt_attrs.AttributeSections == null)
\r
552 foreach (AttributeSection asec in opt_attrs.AttributeSections) {
\r
553 if (asec.Attributes == null)
\r
556 foreach (Attribute a in asec.Attributes){
\r
557 if (a.ResolveType (ec) == null)
\r
560 if (a.Type != TypeManager.indexer_name_type)
\r
564 // So we have found an IndexerName, pull the data out.
\r
566 if (a.Arguments == null || a.Arguments [0] == null){
\r
567 Error_AttributeConstructorMismatch (a.Location);
\r
570 ArrayList pos_args = (ArrayList) a.Arguments [0];
\r
571 if (pos_args.Count == 0){
\r
572 Error_AttributeConstructorMismatch (a.Location);
\r
576 Argument arg = (Argument) pos_args [0];
\r
577 if (!arg.Resolve (ec, a.Location))
\r
580 Expression e = arg.Expr;
\r
581 if (!(e is StringConstant)){
\r
582 Error_AttributeConstructorMismatch (a.Location);
\r
587 // Remove the attribute from the list
\r
589 asec.Attributes.Remove (a);
\r
591 return (((StringConstant) e).Value);
\r
598 // This pulls the condition name out of a Conditional attribute
\r
600 public string Conditional_GetConditionName ()
\r
603 // So we have a Conditional, pull the data out.
\r
605 if (Arguments == null || Arguments [0] == null){
\r
606 Error_AttributeConstructorMismatch (Location);
\r
610 ArrayList pos_args = (ArrayList) Arguments [0];
\r
611 if (pos_args.Count != 1){
\r
612 Error_AttributeConstructorMismatch (Location);
\r
616 Argument arg = (Argument) pos_args [0];
\r
617 if (!(arg.Expr is StringConstant)){
\r
618 Error_AttributeConstructorMismatch (Location);
\r
622 return ((StringConstant) arg.Expr).Value;
\r
626 // This pulls the obsolete message and error flag out of an Obsolete attribute
\r
628 public string Obsolete_GetObsoleteMessage (out bool is_error)
\r
632 // So we have an Obsolete, pull the data out.
\r
634 if (Arguments == null || Arguments [0] == null)
\r
637 ArrayList pos_args = (ArrayList) Arguments [0];
\r
638 if (pos_args.Count == 0)
\r
640 else if (pos_args.Count > 2){
\r
641 Error_AttributeConstructorMismatch (Location);
\r
645 Argument arg = (Argument) pos_args [0];
\r
646 if (!(arg.Expr is StringConstant)){
\r
647 Error_AttributeConstructorMismatch (Location);
\r
651 if (pos_args.Count == 2){
\r
652 Argument arg2 = (Argument) pos_args [1];
\r
653 if (!(arg2.Expr is BoolConstant)){
\r
654 Error_AttributeConstructorMismatch (Location);
\r
657 is_error = ((BoolConstant) arg2.Expr).Value;
\r
660 return ((StringConstant) arg.Expr).Value;
\r
664 // Applies the attributes to the `builder'.
\r
666 public static void ApplyAttributes (EmitContext ec, object builder, object kind,
\r
667 Attributes opt_attrs)
\r
669 ArrayList emitted_attrs = new ArrayList ();
\r
670 ArrayList emitted_targets = new ArrayList ();
\r
671 Type attr_type = null;
\r
673 if (opt_attrs == null)
\r
675 if (opt_attrs.AttributeSections == null)
\r
678 foreach (AttributeSection asec in opt_attrs.AttributeSections) {
\r
679 string attr_target = asec.Target;
\r
681 if (asec.Attributes == null)
\r
684 if (attr_target == "assembly" && !(builder is AssemblyBuilder))
\r
687 if (attr_target == "return" && !(builder is ParameterBuilder))
\r
690 foreach (Attribute a in asec.Attributes) {
\r
691 Location loc = a.Location;
\r
692 CustomAttributeBuilder cb = a.Resolve (ec);
\r
693 attr_type = a.Type;
\r
698 if (!(kind is TypeContainer))
\r
699 if (!CheckAttribute (a, kind)) {
\r
700 Error_AttributeNotValidForElement (a, loc);
\r
705 // Perform the check for duplicate attributes
\r
707 if (emitted_attrs.Contains (attr_type) &&
\r
708 emitted_targets.Contains (attr_target) &&
\r
709 !TypeManager.AreMultipleAllowed (attr_type)) {
\r
710 Report.Error (579, loc, "Duplicate '" + a.Name + "' attribute");
\r
714 if (kind is Method || kind is Operator || kind is InterfaceMethod ||
\r
715 kind is Accessor) {
\r
716 if (attr_type == TypeManager.methodimpl_attr_type) {
\r
717 if (a.ImplOptions == MethodImplOptions.InternalCall)
\r
718 ((MethodBuilder) builder).
\r
719 SetImplementationFlags (
\r
720 MethodImplAttributes.InternalCall |
\r
721 MethodImplAttributes.Runtime);
\r
723 ((MethodBuilder) builder).SetCustomAttribute (cb);
\r
724 } else if (attr_type != TypeManager.dllimport_type){
\r
725 ((MethodBuilder) builder).SetCustomAttribute (cb);
\r
727 } else if (kind is Constructor) {
\r
728 ((ConstructorBuilder) builder).SetCustomAttribute (cb);
\r
729 } else if (kind is Field) {
\r
730 ((FieldBuilder) builder).SetCustomAttribute (cb);
\r
731 } else if (kind is Property || kind is Indexer ||
\r
732 kind is InterfaceProperty || kind is InterfaceIndexer) {
\r
733 ((PropertyBuilder) builder).SetCustomAttribute (cb);
\r
734 } else if (kind is Event || kind is InterfaceEvent) {
\r
735 ((MyEventBuilder) builder).SetCustomAttribute (cb);
\r
736 } else if (kind is ParameterBuilder) {
\r
738 if (attr_type == TypeManager.marshal_as_attr_type) {
\r
739 UnmanagedMarshal marshal =
\r
740 UnmanagedMarshal.DefineUnmanagedMarshal (a.UnmanagedType);
\r
742 ((ParameterBuilder) builder).SetMarshal (marshal);
\r
746 ((ParameterBuilder) builder).SetCustomAttribute (cb);
\r
747 } catch (System.ArgumentException) {
\r
748 Report.Warning (-24, loc,
\r
749 "The Microsoft Runtime cannot set attributes \n" +
\r
750 "on the return type of a method. Please use the \n" +
\r
751 "Mono runtime instead.");
\r
755 } else if (kind is Enum) {
\r
756 ((TypeBuilder) builder).SetCustomAttribute (cb);
\r
758 } else if (kind is TypeContainer) {
\r
759 TypeContainer tc = (TypeContainer) kind;
\r
762 tc.Targets = a.Targets;
\r
763 tc.AllowMultiple = a.AllowMultiple;
\r
764 tc.Inherited = a.Inherited;
\r
766 TypeManager.RegisterAttributeAllowMultiple (tc.TypeBuilder,
\r
769 } else if (attr_type == TypeManager.default_member_type) {
\r
770 if (tc.Indexers != null) {
\r
771 Report.Error (646, loc,
\r
772 "Cannot specify the DefaultMember attribute on" +
\r
773 " a type containing an indexer");
\r
778 if (!CheckAttribute (a, kind)) {
\r
779 Error_AttributeNotValidForElement (a, loc);
\r
785 ((TypeBuilder) builder).SetCustomAttribute (cb);
\r
786 } catch (System.ArgumentException) {
\r
789 "The CharSet named property on StructLayout\n"+
\r
790 "\tdoes not work correctly on Microsoft.NET\n"+
\r
791 "\tYou might want to remove the CharSet declaration\n"+
\r
792 "\tor compile using the Mono runtime instead of the\n"+
\r
793 "\tMicrosoft .NET runtime");
\r
796 } else if (kind is Interface) {
\r
797 Interface iface = (Interface) kind;
\r
799 if ((attr_type == TypeManager.default_member_type) &&
\r
800 (iface.InterfaceIndexers != null)) {
\r
803 "Cannot specify the DefaultMember attribute on" +
\r
804 " a type containing an indexer");
\r
808 if (!CheckAttribute (a, kind)) {
\r
809 Error_AttributeNotValidForElement (a, loc);
\r
813 ((TypeBuilder) builder).SetCustomAttribute (cb);
\r
814 } else if (kind is AssemblyBuilder){
\r
815 ((AssemblyBuilder) builder).SetCustomAttribute (cb);
\r
816 } else if (kind is ModuleBuilder) {
\r
817 ((ModuleBuilder) builder).SetCustomAttribute (cb);
\r
818 } else if (kind is FieldBuilder) {
\r
819 ((FieldBuilder) builder).SetCustomAttribute (cb);
\r
821 throw new Exception ("Unknown kind: " + kind);
\r
824 // Once an attribute type has been emitted once we
\r
825 // keep track of the info to prevent multiple occurences
\r
826 // for attributes which do not explicitly allow it
\r
828 if (!emitted_attrs.Contains (attr_type))
\r
829 emitted_attrs.Add (attr_type);
\r
832 // We keep of this target-wise and so emitted targets
\r
835 if (!emitted_targets.Contains (attr_target))
\r
836 emitted_targets.Add (attr_target);
\r
843 public MethodBuilder DefinePInvokeMethod (EmitContext ec, TypeBuilder builder, string name,
\r
844 MethodAttributes flags, Type ret_type, Type [] param_types)
\r
847 // We extract from the attribute the information we need
\r
850 if (Arguments == null) {
\r
851 Console.WriteLine ("Internal error : this is not supposed to happen !");
\r
855 Type = CheckAttributeType (ec);
\r
859 ArrayList named_args = new ArrayList ();
\r
861 ArrayList pos_args = (ArrayList) Arguments [0];
\r
862 if (Arguments.Count > 1)
\r
863 named_args = (ArrayList) Arguments [1];
\r
866 string dll_name = null;
\r
868 Argument tmp = (Argument) pos_args [0];
\r
870 if (!tmp.Resolve (ec, Location))
\r
873 if (tmp.Expr is Constant)
\r
874 dll_name = (string) ((Constant) tmp.Expr).GetValue ();
\r
876 Error_AttributeArgumentNotValid ();
\r
880 // Now we process the named arguments
\r
881 CallingConvention cc = CallingConvention.Winapi;
\r
882 CharSet charset = CharSet.Ansi;
\r
883 bool preserve_sig = true;
\r
884 bool exact_spelling = false;
\r
885 bool set_last_err = false;
\r
886 string entry_point = null;
\r
888 for (int i = 0; i < named_args.Count; i++) {
\r
890 DictionaryEntry de = (DictionaryEntry) named_args [i];
\r
892 string member_name = (string) de.Key;
\r
893 Argument a = (Argument) de.Value;
\r
895 if (!a.Resolve (ec, Location))
\r
898 Expression member = Expression.MemberLookup (
\r
899 ec, Type, member_name,
\r
900 MemberTypes.Field | MemberTypes.Property,
\r
901 BindingFlags.Public | BindingFlags.Instance,
\r
904 if (member == null || !(member is FieldExpr)) {
\r
905 Error_InvalidNamedArgument (member_name);
\r
909 if (member is FieldExpr) {
\r
910 FieldExpr fe = (FieldExpr) member;
\r
911 FieldInfo fi = fe.FieldInfo;
\r
913 if (fi.IsInitOnly) {
\r
914 Error_InvalidNamedArgument (member_name);
\r
918 if (a.Expr is Constant) {
\r
919 Constant c = (Constant) a.Expr;
\r
921 if (member_name == "CallingConvention")
\r
922 cc = (CallingConvention) c.GetValue ();
\r
923 else if (member_name == "CharSet")
\r
924 charset = (CharSet) c.GetValue ();
\r
925 else if (member_name == "EntryPoint")
\r
926 entry_point = (string) c.GetValue ();
\r
927 else if (member_name == "SetLastError")
\r
928 set_last_err = (bool) c.GetValue ();
\r
929 else if (member_name == "ExactSpelling")
\r
930 exact_spelling = (bool) c.GetValue ();
\r
931 else if (member_name == "PreserveSig")
\r
932 preserve_sig = (bool) c.GetValue ();
\r
934 Error_AttributeArgumentNotValid ();
\r
941 if (entry_point == null)
\r
942 entry_point = name;
\r
944 MethodBuilder mb = builder.DefinePInvokeMethod (
\r
945 name, dll_name, entry_point, flags | MethodAttributes.HideBySig,
\r
946 CallingConventions.Standard,
\r
953 mb.SetImplementationFlags (MethodImplAttributes.PreserveSig);
\r
960 public class AttributeSection {
\r
961 public readonly string Target;
\r
962 public readonly ArrayList Attributes;
\r
964 public AttributeSection (string target, ArrayList attrs)
\r
967 Attributes = attrs;
\r
972 public class Attributes {
\r
973 public ArrayList AttributeSections;
\r
975 public Attributes (AttributeSection a)
\r
977 AttributeSections = new ArrayList ();
\r
978 AttributeSections.Add (a);
\r
982 public void AddAttributeSection (AttributeSection a)
\r
984 if (a != null && !AttributeSections.Contains (a))
\r
985 AttributeSections.Add (a);
\r
988 public bool Contains (Type t)
\r
990 foreach (AttributeSection attr_section in AttributeSections){
\r
991 foreach (Attribute a in attr_section.Attributes){
\r