2 // outline -- support for rendering in monop
3 // Some code stolen from updater.cs in monodoc.
6 // Ben Maurer (bmaurer@users.sourceforge.net)
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 using System
.Collections
;
34 using System
.CodeDom
.Compiler
;
38 using IKVM
.Reflection
;
39 using Type
=IKVM
.Reflection
.Type
;
41 using System
.Reflection
;
44 namespace Mono
.CSharp
{
46 public static class TypeExtensions
{
47 public static string GetNamespace (this Type t
)
49 // IKVM crashes here with a null ref sometimes
58 public class Outline
{
65 Type type_multicast_delegate
, type_object
, type_value_type
, type_int
, type_flags_attribute
, type_obsolete_attribute
, type_param_array_attribute
;
71 public Outline (System
.Type t
, TextWriter output
, bool declared_only
, bool show_private
, bool filter_obsolete
)
73 throw new NotImplementedException ();
76 public Outline (Universe universe
, Assembly mscorlib
, Type t
, TextWriter output
, bool declared_only
, bool show_private
, bool filter_obsolete
)
79 throw new ArgumentNullException ("universe");
81 throw new ArgumentNullException ("mscorlib");
82 this.universe
= universe
;
83 this.mscorlib
= mscorlib
;
85 this.o
= new IndentedTextWriter (output
, "\t");
86 this.declared_only
= declared_only
;
87 this.show_private
= show_private
;
88 this.filter_obsolete
= filter_obsolete
;
90 type_multicast_delegate
= mscorlib
.GetType("System.MulticastDelegate");
91 type_object
= mscorlib
.GetType ("System.Object");
92 type_value_type
= mscorlib
.GetType ("System.ValueType");
93 type_int
= mscorlib
.GetType ("System.Int32");
94 type_flags_attribute
= mscorlib
.GetType ("System.FlagsAttribute");
95 type_obsolete_attribute
= mscorlib
.GetType ("System.ObsoleteAttribute");
96 type_param_array_attribute
= mscorlib
.GetType ("System.ParamArrayAttribute");
99 public Outline (Type t
, TextWriter output
, bool declared_only
, bool show_private
, bool filter_obsolete
)
102 this.o
= new IndentedTextWriter (output
, "\t");
103 this.declared_only
= declared_only
;
104 this.show_private
= show_private
;
105 this.filter_obsolete
= filter_obsolete
;
107 type_multicast_delegate
= typeof (System
.MulticastDelegate
);
108 type_object
= typeof (object);
109 type_value_type
= typeof (ValueType
);
110 type_int
= typeof (int);
111 type_flags_attribute
= typeof (FlagsAttribute
);
112 type_obsolete_attribute
= typeof (ObsoleteAttribute
);
113 type_param_array_attribute
= typeof (ParamArrayAttribute
);
117 public void OutlineType ()
121 OutlineAttributes ();
122 o
.Write (GetTypeVisibility (t
));
124 if (t
.IsClass
&& !t
.IsSubclassOf (type_multicast_delegate
)) {
126 o
.Write (t
.IsAbstract
? " static" : " sealed");
127 else if (t
.IsAbstract
)
128 o
.Write (" abstract");
132 o
.Write (GetTypeKind (t
));
135 Type
[] interfaces
= (Type
[]) Comparer
.Sort (TypeGetInterfaces (t
, declared_only
));
136 Type parent
= t
.BaseType
;
138 if (t
.IsSubclassOf (type_multicast_delegate
)) {
141 method
= t
.GetMethod ("Invoke");
143 o
.Write (FormatType (method
.ReturnType
));
145 o
.Write (GetTypeName (t
));
147 OutlineParams (method
.GetParameters ());
150 WriteGenericConstraints (t
.GetGenericArguments ());
156 o
.Write (GetTypeName (t
));
157 if (((parent
!= null && parent
!= type_object
&& parent
!= type_value_type
) || interfaces
.Length
!= 0) && ! t
.IsEnum
) {
161 if (parent
!= null && parent
!= type_object
&& parent
!= type_value_type
) {
162 o
.Write (FormatType (parent
));
166 foreach (Type intf
in interfaces
) {
167 if (!first
) o
.Write (", ");
170 o
.Write (FormatType (intf
));
175 Type underlyingType
= t
.GetEnumUnderlyingType ();
176 if (underlyingType
!= type_int
)
177 o
.Write (" : {0}", FormatType (underlyingType
));
179 WriteGenericConstraints (t
.GetGenericArguments ());
184 bool is_first
= true;
185 foreach (FieldInfo fi
in t
.GetFields (BindingFlags
.Public
| BindingFlags
.Static
)) {
193 o
.Indent
--; o
.WriteLine ("}");
199 foreach (ConstructorInfo ci
in t
.GetConstructors (DefaultFlags
)) {
200 if (! ShowMember (ci
))
207 OutlineMemberAttribute (ci
);
208 OutlineConstructor (ci
);
216 foreach (MethodInfo m
in Comparer
.Sort (t
.GetMethods (DefaultFlags
))) {
218 if (! ShowMember (m
))
221 if ((m
.Attributes
& MethodAttributes
.SpecialName
) != 0)
228 OutlineMemberAttribute (m
);
236 foreach (MethodInfo m
in t
.GetMethods (DefaultFlags
)) {
238 if (! ShowMember (m
))
241 if ((m
.Attributes
& MethodAttributes
.SpecialName
) == 0)
243 if (!(m
.Name
.StartsWith ("op_")))
250 OutlineMemberAttribute (m
);
258 foreach (PropertyInfo pi
in Comparer
.Sort (t
.GetProperties (DefaultFlags
))) {
260 if (! ((pi
.CanRead
&& ShowMember (pi
.GetGetMethod (true))) ||
261 (pi
.CanWrite
&& ShowMember (pi
.GetSetMethod (true)))))
268 OutlineMemberAttribute (pi
);
269 OutlineProperty (pi
);
276 foreach (FieldInfo fi
in t
.GetFields (DefaultFlags
)) {
278 if (! ShowMember (fi
))
285 OutlineMemberAttribute (fi
);
293 foreach (EventInfo ei
in Comparer
.Sort (t
.GetEvents (DefaultFlags
))) {
295 if (! ShowMember (ei
.GetAddMethod (true)))
302 OutlineMemberAttribute (ei
);
310 foreach (Type ntype
in Comparer
.Sort (t
.GetNestedTypes (DefaultFlags
))) {
312 if (! ShowMember (ntype
))
320 new Outline (universe
, mscorlib
, ntype
, o
, declared_only
, show_private
, filter_obsolete
).OutlineType ();
322 new Outline (ntype
, o
, declared_only
, show_private
, filter_obsolete
).OutlineType ();
326 o
.Indent
--; o
.WriteLine ("}");
329 BindingFlags DefaultFlags
{
331 BindingFlags f
= BindingFlags
.Instance
| BindingFlags
.Static
| BindingFlags
.Public
| BindingFlags
.NonPublic
;
334 f
|= BindingFlags
.DeclaredOnly
;
340 // FIXME: add other interesting attributes?
341 void OutlineAttributes ()
343 if (t
.IsSerializable
)
344 o
.WriteLine ("[Serializable]");
346 if (t
.IsDefined (type_flags_attribute
, true))
347 o
.WriteLine ("[Flags]");
349 if (t
.IsDefined (type_obsolete_attribute
, true))
350 o
.WriteLine ("[Obsolete]");
353 void OutlineMemberAttribute (MemberInfo mi
)
355 var attrs
= mi
.GetCustomAttributesData ();
359 foreach (var attr
in attrs
)
363 void OutlineEvent (EventInfo ei
)
365 MethodBase accessor
= ei
.GetAddMethod (true);
367 o
.Write (GetMethodVisibility (accessor
));
369 o
.Write (FormatType (ei
.EventHandlerType
));
375 void OutlineConstructor (ConstructorInfo ci
)
377 o
.Write (GetMethodVisibility (ci
));
378 o
.Write (RemoveGenericArity (t
.Name
));
380 OutlineParams (ci
.GetParameters ());
385 void OutlineProperty (PropertyInfo pi
)
387 ParameterInfo
[] idxp
= pi
.GetIndexParameters ();
388 MethodBase g
= pi
.GetGetMethod (true);
389 MethodBase s
= pi
.GetSetMethod (true);
390 MethodBase accessor
= g
!= null ? g
: s
;
392 if (pi
.CanRead
&& pi
.CanWrite
) {
395 // Get the more accessible accessor
396 if ((g
.Attributes
& MethodAttributes
.MemberAccessMask
) !=
397 (s
.Attributes
& MethodAttributes
.MemberAccessMask
)) {
399 if (g
.IsPublic
) accessor
= g
;
400 else if (s
.IsPublic
) accessor
= s
;
401 else if (g
.IsFamilyOrAssembly
) accessor
= g
;
402 else if (s
.IsFamilyOrAssembly
) accessor
= s
;
403 else if (g
.IsAssembly
|| g
.IsFamily
) accessor
= g
;
404 else if (s
.IsAssembly
|| s
.IsFamily
) accessor
= s
;
408 o
.Write (GetMethodVisibility (accessor
));
409 o
.Write (GetMethodModifiers (accessor
));
410 o
.Write (FormatType (pi
.PropertyType
));
413 if (idxp
.Length
== 0)
417 OutlineParams (idxp
);
424 if (g
!= null && ShowMember (g
)) {
425 if ((g
.Attributes
& MethodAttributes
.MemberAccessMask
) !=
426 (accessor
.Attributes
& MethodAttributes
.MemberAccessMask
))
427 o
.Write (GetMethodVisibility (g
));
428 o
.WriteLine ("get;");
431 if (s
!= null && ShowMember (s
)) {
432 if ((s
.Attributes
& MethodAttributes
.MemberAccessMask
) !=
433 (accessor
.Attributes
& MethodAttributes
.MemberAccessMask
))
434 o
.Write (GetMethodVisibility (s
));
435 o
.WriteLine ("set;");
442 void OutlineMethod (MethodInfo mi
)
444 if (MethodIsExplicitIfaceImpl (mi
)) {
445 o
.Write (FormatType (mi
.ReturnType
));
447 // MSFT has no way to get the method that we are overriding
448 // from the interface. this would allow us to pretty print
449 // the type name (and be more correct if there compiler
450 // were to do some strange naming thing).
452 o
.Write (GetMethodVisibility (mi
));
453 o
.Write (GetMethodModifiers (mi
));
454 o
.Write (FormatType (mi
.ReturnType
));
459 o
.Write (FormatGenericParams (mi
.GetGenericArguments ()));
461 OutlineParams (mi
.GetParameters ());
463 WriteGenericConstraints (mi
.GetGenericArguments ());
467 void OutlineOperator (MethodInfo mi
)
469 o
.Write (GetMethodVisibility (mi
));
470 o
.Write (GetMethodModifiers (mi
));
471 if (mi
.Name
== "op_Explicit" || mi
.Name
== "op_Implicit") {
472 o
.Write (mi
.Name
.Substring (3).ToLower ());
473 o
.Write (" operator ");
474 o
.Write (FormatType (mi
.ReturnType
));
476 o
.Write (FormatType (mi
.ReturnType
));
477 o
.Write (" operator ");
478 o
.Write (OperatorFromName (mi
.Name
));
481 OutlineParams (mi
.GetParameters ());
485 void OutlineParams (ParameterInfo
[] pi
)
488 foreach (ParameterInfo p
in pi
) {
489 if (p
.ParameterType
.IsByRef
) {
490 o
.Write (p
.IsOut
? "out " : "ref ");
491 o
.Write (FormatType (p
.ParameterType
.GetElementType ()));
492 } else if (p
.IsDefined (type_param_array_attribute
, false)) {
494 o
.Write (FormatType (p
.ParameterType
));
496 o
.Write (FormatType (p
.ParameterType
));
501 if (i
+ 1 < pi
.Length
)
507 void OutlineField (FieldInfo fi
)
509 if (fi
.IsPublic
) o
.Write ("public ");
510 if (fi
.IsFamily
) o
.Write ("protected ");
511 if (fi
.IsPrivate
) o
.Write ("private ");
512 if (fi
.IsAssembly
) o
.Write ("internal ");
513 if (fi
.IsLiteral
) o
.Write ("const ");
514 else if (fi
.IsStatic
) o
.Write ("static ");
515 if (fi
.IsInitOnly
) o
.Write ("readonly ");
517 o
.Write (FormatType (fi
.FieldType
));
521 object v
= fi
.GetRawConstantValue ();
523 // TODO: Escape values here
526 o
.Write ("'{0}'", v
);
527 else if (v
is string)
528 o
.Write ("\"{0}\"", v
);
530 o
.Write (fi
.GetRawConstantValue ());
535 static string GetMethodVisibility (MethodBase m
)
537 // itnerfaces have no modifiers here
538 if (m
.DeclaringType
.IsInterface
)
541 if (m
.IsPublic
) return "public ";
542 if (m
.IsFamily
) return "protected ";
543 if (m
.IsPrivate
) return "private ";
544 if (m
.IsAssembly
) return "internal ";
549 static string GetMethodModifiers (MethodBase method
)
554 if (method
.IsFinal
) {
555 // This will happen if you have
557 // public void A () {}
558 // static void Main () {}
564 // A needs to be virtual (the CLR requires
565 // methods implementing an iface be virtual),
566 // but can not be inherited. It also can not
567 // be inherited. In C# this is represented
568 // with no special modifiers
570 if (method
.IsVirtual
)
575 // all interface methods are "virtual" but we don't say that in c#
576 if (method
.IsVirtual
&& !method
.DeclaringType
.IsInterface
) {
577 if (method
.IsAbstract
)
580 return ((method
.Attributes
& MethodAttributes
.NewSlot
) != 0) ?
588 string GetTypeKind (Type t
)
593 if (t
.IsSubclassOf (type_multicast_delegate
))
605 static string GetTypeVisibility (Type t
)
607 switch (t
.Attributes
& TypeAttributes
.VisibilityMask
){
608 case TypeAttributes
.Public
:
609 case TypeAttributes
.NestedPublic
:
612 case TypeAttributes
.NestedFamily
:
613 case TypeAttributes
.NestedFamANDAssem
:
614 case TypeAttributes
.NestedFamORAssem
:
622 string FormatGenericParams (Type
[] args
)
624 StringBuilder sb
= new StringBuilder ();
625 if (args
.Length
== 0)
629 for (int i
= 0; i
< args
.Length
; i
++) {
632 sb
.Append (FormatType (args
[i
]));
635 return sb
.ToString ();
638 // TODO: fine tune this so that our output is less verbose. We need to figure
639 // out a way to do this while not making things confusing.
640 string FormatType (Type t
)
645 string type
= GetFullName (t
);
647 return t
.ToString ();
649 if (!type
.StartsWith ("System.")) {
650 if (type
.IndexOf (".") == -1)
652 if (t
.GetNamespace () == this.t
.GetNamespace ())
657 if (t
.HasElementType
) {
658 Type et
= t
.GetElementType ();
660 return FormatType (et
) + " []";
662 return FormatType (et
) + " *";
664 return "ref " + FormatType (et
);
668 case "System.Byte": return "byte";
669 case "System.SByte": return "sbyte";
670 case "System.Int16": return "short";
671 case "System.Int32": return "int";
672 case "System.Int64": return "long";
674 case "System.UInt16": return "ushort";
675 case "System.UInt32": return "uint";
676 case "System.UInt64": return "ulong";
678 case "System.Single": return "float";
679 case "System.Double": return "double";
680 case "System.Decimal": return "decimal";
681 case "System.Boolean": return "bool";
682 case "System.Char": return "char";
683 case "System.String": return "string";
685 case "System.Object": return "object";
686 case "System.Void": return "void";
689 if (type
.LastIndexOf(".") == 6)
690 return type
.Substring(7);
693 // If the namespace of the type is the namespace of what
694 // we are printing (or is a member of one if its children
695 // don't print it. This basically means that in C# we would
696 // automatically get the namespace imported by virtue of the
697 // namespace {} block.
699 if (this.t
.Namespace
!= null && (this.t
.Namespace
.StartsWith (t
.Namespace
+ ".") || t
.Namespace
== this.t
.Namespace
))
700 return type
.Substring (t
.Namespace
.Length
+ 1);
705 public static string RemoveGenericArity (string name
)
708 StringBuilder sb
= new StringBuilder ();
709 while (start
< name
.Length
) {
710 int pos
= name
.IndexOf ('`', start
);
712 sb
.Append (name
.Substring (start
));
715 sb
.Append (name
.Substring (start
, pos
-start
));
719 while ((pos
< name
.Length
) && Char
.IsNumber (name
[pos
]))
725 return sb
.ToString ();
728 string GetTypeName (Type t
)
730 StringBuilder sb
= new StringBuilder ();
732 return sb
.ToString ();
735 void GetTypeName (StringBuilder sb
, Type t
)
737 sb
.Append (RemoveGenericArity (t
.Name
));
738 sb
.Append (FormatGenericParams (t
.GetGenericArguments ()));
741 string GetFullName (Type t
)
743 StringBuilder sb
= new StringBuilder ();
744 GetFullName_recursed (sb
, t
, false);
745 return sb
.ToString ();
748 void GetFullName_recursed (StringBuilder sb
, Type t
, bool recursed
)
750 if (t
.IsGenericParameter
) {
755 if (t
.DeclaringType
!= null) {
756 GetFullName_recursed (sb
, t
.DeclaringType
, true);
762 ns
= t
.GetNamespace ();
763 if ((ns
!= null) && (ns
!= "")) {
772 void WriteGenericConstraints (Type
[] args
)
775 foreach (Type t
in args
) {
777 Type
[] ifaces
= TypeGetInterfaces (t
, true);
779 GenericParameterAttributes attrs
= t
.GenericParameterAttributes
& GenericParameterAttributes
.SpecialConstraintMask
;
780 GenericParameterAttributes
[] interesting
= {
781 GenericParameterAttributes
.ReferenceTypeConstraint
,
782 GenericParameterAttributes
.NotNullableValueTypeConstraint
,
783 GenericParameterAttributes
.DefaultConstructorConstraint
786 if (t
.BaseType
!= type_object
|| ifaces
.Length
!= 0 || attrs
!= 0) {
788 o
.Write (FormatType (t
));
792 if (t
.BaseType
!= type_object
) {
793 o
.Write (FormatType (t
.BaseType
));
797 foreach (Type iface
in ifaces
) {
802 o
.Write (FormatType (iface
));
805 foreach (GenericParameterAttributes a
in interesting
) {
806 if ((attrs
& a
) == 0)
814 case GenericParameterAttributes
.ReferenceTypeConstraint
:
817 case GenericParameterAttributes
.NotNullableValueTypeConstraint
:
820 case GenericParameterAttributes
.DefaultConstructorConstraint
:
828 string OperatorFromName (string name
)
831 case "op_UnaryPlus": return "+";
832 case "op_UnaryNegation": return "-";
833 case "op_LogicalNot": return "!";
834 case "op_OnesComplement": return "~";
835 case "op_Increment": return "++";
836 case "op_Decrement": return "--";
837 case "op_True": return "true";
838 case "op_False": return "false";
839 case "op_Addition": return "+";
840 case "op_Subtraction": return "-";
841 case "op_Multiply": return "*";
842 case "op_Division": return "/";
843 case "op_Modulus": return "%";
844 case "op_BitwiseAnd": return "&";
845 case "op_BitwiseOr": return "|";
846 case "op_ExclusiveOr": return "^";
847 case "op_LeftShift": return "<<";
848 case "op_RightShift": return ">>";
849 case "op_Equality": return "==";
850 case "op_Inequality": return "!=";
851 case "op_GreaterThan": return ">";
852 case "op_LessThan": return "<";
853 case "op_GreaterThanOrEqual": return ">=";
854 case "op_LessThanOrEqual": return "<=";
855 default: return name
;
859 bool MethodIsExplicitIfaceImpl (MethodBase mb
)
861 if (!(mb
.IsFinal
&& mb
.IsVirtual
&& mb
.IsPrivate
))
864 // UGH msft has no way to get the info about what method is
865 // getting overriden. Another reason to use cecil :-)
867 //MethodInfo mi = mb as MethodInfo;
871 //Console.WriteLine (mi.GetBaseDefinition ().DeclaringType);
872 //return mi.GetBaseDefinition ().DeclaringType.IsInterface;
874 // So, we guess that virtual final private methods only come
879 bool ShowMember (MemberInfo mi
)
881 if (mi
.MemberType
== MemberTypes
.Constructor
&& ((MethodBase
) mi
).IsStatic
)
887 if (filter_obsolete
&& mi
.IsDefined (type_obsolete_attribute
, false))
890 switch (mi
.MemberType
) {
891 case MemberTypes
.Constructor
:
892 case MemberTypes
.Method
:
893 MethodBase mb
= mi
as MethodBase
;
895 if (mb
.IsFamily
|| mb
.IsPublic
|| mb
.IsFamilyOrAssembly
)
898 if (MethodIsExplicitIfaceImpl (mb
))
904 case MemberTypes
.Field
:
905 FieldInfo fi
= mi
as FieldInfo
;
907 if (fi
.IsFamily
|| fi
.IsPublic
|| fi
.IsFamilyOrAssembly
)
913 case MemberTypes
.NestedType
:
914 case MemberTypes
.TypeInfo
:
917 switch (t
.Attributes
& TypeAttributes
.VisibilityMask
){
918 case TypeAttributes
.Public
:
919 case TypeAttributes
.NestedPublic
:
920 case TypeAttributes
.NestedFamily
:
921 case TypeAttributes
.NestedFamORAssem
:
932 static Type
[] TypeGetInterfaces (Type t
, bool declonly
)
934 if (t
.IsGenericParameter
)
937 Type
[] ifaces
= t
.GetInterfaces ();
941 // Handle Object. Also, optimize for no interfaces
942 if (t
.BaseType
== null || ifaces
.Length
== 0)
945 ArrayList ar
= new ArrayList ();
947 foreach (Type i
in ifaces
)
948 if (! i
.IsAssignableFrom (t
.BaseType
))
951 return (Type
[]) ar
.ToArray (typeof (Type
));
955 public class Comparer
: IComparer
{
956 delegate int ComparerFunc (object a
, object b
);
960 Comparer (ComparerFunc f
)
965 public int Compare (object a
, object b
)
970 static int CompareType (object a
, object b
)
972 Type type1
= (Type
) a
;
973 Type type2
= (Type
) b
;
975 return string.Compare (type1
.Name
, type2
.Name
);
979 // static Comparer TypeComparer = new Comparer (new ComparerFunc (CompareType));
981 // static Type [] Sort (Type [] types)
983 // Array.Sort (types, TypeComparer);
987 static int CompareMemberInfo (object a
, object b
)
989 return string.Compare (((MemberInfo
) a
).Name
, ((MemberInfo
) b
).Name
);
992 static Comparer MemberInfoComparer
= new Comparer (new ComparerFunc (CompareMemberInfo
));
994 public static MemberInfo
[] Sort (MemberInfo
[] inf
)
996 Array
.Sort (inf
, MemberInfoComparer
);
1000 static int CompareMethodBase (object a
, object b
)
1002 MethodBase aa
= (MethodBase
) a
, bb
= (MethodBase
) b
;
1004 if (aa
.IsStatic
== bb
.IsStatic
) {
1005 int c
= CompareMemberInfo (a
, b
);
1008 ParameterInfo
[] ap
, bp
;
1011 // Sort overloads by the names of their types
1012 // put methods with fewer params first.
1015 ap
= aa
.GetParameters ();
1016 bp
= bb
.GetParameters ();
1017 int n
= System
.Math
.Min (ap
.Length
, bp
.Length
);
1019 for (int i
= 0; i
< n
; i
++)
1020 if ((c
= CompareType (ap
[i
].ParameterType
, bp
[i
].ParameterType
)) != 0)
1023 return ap
.Length
.CompareTo (bp
.Length
);
1031 static Comparer MethodBaseComparer
= new Comparer (new ComparerFunc (CompareMethodBase
));
1033 public static MethodBase
[] Sort (MethodBase
[] inf
)
1035 Array
.Sort (inf
, MethodBaseComparer
);
1039 static int ComparePropertyInfo (object a
, object b
)
1041 PropertyInfo aa
= (PropertyInfo
) a
, bb
= (PropertyInfo
) b
;
1043 bool astatic
= (aa
.CanRead
? aa
.GetGetMethod (true) : aa
.GetSetMethod (true)).IsStatic
;
1044 bool bstatic
= (bb
.CanRead
? bb
.GetGetMethod (true) : bb
.GetSetMethod (true)).IsStatic
;
1046 if (astatic
== bstatic
)
1047 return CompareMemberInfo (a
, b
);
1055 static Comparer PropertyInfoComparer
= new Comparer (new ComparerFunc (ComparePropertyInfo
));
1057 public static PropertyInfo
[] Sort (PropertyInfo
[] inf
)
1059 Array
.Sort (inf
, PropertyInfoComparer
);
1063 static int CompareEventInfo (object a
, object b
)
1065 EventInfo aa
= (EventInfo
) a
, bb
= (EventInfo
) b
;
1067 bool astatic
= aa
.GetAddMethod (true).IsStatic
;
1068 bool bstatic
= bb
.GetAddMethod (true).IsStatic
;
1070 if (astatic
== bstatic
)
1071 return CompareMemberInfo (a
, b
);
1079 static Comparer EventInfoComparer
= new Comparer (new ComparerFunc (CompareEventInfo
));
1081 public static EventInfo
[] Sort (EventInfo
[] inf
)
1083 Array
.Sort (inf
, EventInfoComparer
);