1
+ using EventBuilder . Entities ;
2
+ using Mono . Cecil ;
3
+ using System . Collections . Generic ;
4
+ using System . Linq ;
5
+
6
+ namespace EventBuilder . Cecil
7
+ {
8
+ public static class StaticEventTemplateInformation
9
+ {
10
+ private static string GetEventArgsTypeForEvent ( EventDefinition ei )
11
+ {
12
+ // Find the EventArgs type parameter of the event via digging around via reflection
13
+ var type = ei . EventType . Resolve ( ) ;
14
+ var invoke = type . Methods . First ( x => x . Name == "Invoke" ) ;
15
+ if ( invoke . Parameters . Count < 1 ) return null ;
16
+
17
+ var param = invoke . Parameters . Count == 1 ? invoke . Parameters [ 0 ] : invoke . Parameters [ 1 ] ;
18
+ var ret = param . ParameterType . FullName ;
19
+
20
+ var generic = ei . EventType as GenericInstanceType ;
21
+ if ( generic != null )
22
+ {
23
+ foreach (
24
+ var kvp in
25
+ type . GenericParameters . Zip ( generic . GenericArguments , ( name , actual ) => new { name , actual } ) )
26
+ {
27
+ var realType = GetRealTypeName ( kvp . actual ) ;
28
+
29
+ ret = ret . Replace ( kvp . name . FullName , realType ) ;
30
+ }
31
+ }
32
+
33
+ // NB: Inner types in Mono.Cecil get reported as 'Foo/Bar'
34
+ return ret . Replace ( '/' , '.' ) ;
35
+ }
36
+
37
+ private static string GetRealTypeName ( TypeDefinition t )
38
+ {
39
+ if ( t . GenericParameters . Count == 0 ) return t . FullName ;
40
+
41
+ var ret = string . Format ( "{0}<{1}>" ,
42
+ t . Namespace + "." + t . Name ,
43
+ string . Join ( "," , t . GenericParameters . Select ( x => GetRealTypeName ( x . Resolve ( ) ) ) ) ) ;
44
+
45
+ // NB: Inner types in Mono.Cecil get reported as 'Foo/Bar'
46
+ return ret . Replace ( '/' , '.' ) ;
47
+ }
48
+
49
+ private static string GetRealTypeName ( TypeReference t )
50
+ {
51
+ var generic = t as GenericInstanceType ;
52
+ if ( generic == null ) return t . FullName ;
53
+
54
+ var ret = string . Format ( "{0}<{1}>" ,
55
+ generic . Namespace + "." + generic . Name ,
56
+ string . Join ( "," , generic . GenericArguments . Select ( x => GetRealTypeName ( x ) ) ) ) ;
57
+
58
+ // NB: Inner types in Mono.Cecil get reported as 'Foo/Bar'
59
+ return ret . Replace ( '/' , '.' ) ;
60
+ }
61
+
62
+ private static EventDefinition [ ] GetPublicEvents ( TypeDefinition t )
63
+ {
64
+ return
65
+ t . Events
66
+
67
+ . Where ( x =>
68
+ {
69
+ return x . AddMethod . IsPublic && GetEventArgsTypeForEvent ( x ) != null ;
70
+ } )
71
+ . ToArray ( ) ;
72
+ }
73
+
74
+ public static NamespaceInfo [ ] Create ( AssemblyDefinition [ ] targetAssemblies )
75
+ {
76
+ var publicTypesWithEvents = targetAssemblies
77
+ . SelectMany ( x => SafeTypes . GetSafeTypes ( x ) )
78
+ . Where ( x => x . IsPublic && ! x . HasGenericParameters )
79
+ . Select ( x => new { Type = x , Events = GetPublicEvents ( x ) } )
80
+ . Where ( x => x . Events . Length > 0 )
81
+ . ToArray ( ) ;
82
+
83
+ var garbageNamespaceList = new [ ]
84
+ {
85
+ "ReactiveUI.Events"
86
+ } ;
87
+
88
+ var namespaceData = publicTypesWithEvents
89
+ . GroupBy ( x => x . Type . Namespace )
90
+ . Where ( x => ! garbageNamespaceList . Contains ( x . Key ) )
91
+ . Select ( x => new NamespaceInfo
92
+ {
93
+ Name = x . Key ,
94
+ Types = x . Select ( y => new PublicTypeInfo
95
+ {
96
+ Name = y . Type . Name ,
97
+ Type = y . Type ,
98
+ Events = y . Events . Select ( z => new PublicEventInfo
99
+ {
100
+ Name = z . Name ,
101
+ EventHandlerType = GetRealTypeName ( z . EventType ) ,
102
+ EventArgsType = GetEventArgsTypeForEvent ( z )
103
+ } ) . ToArray ( )
104
+ } ) . ToArray ( )
105
+ } ) . ToArray ( ) ;
106
+
107
+ foreach ( var type in namespaceData . SelectMany ( x => x . Types ) )
108
+ {
109
+ var parentWithEvents = GetParents ( type . Type ) . FirstOrDefault ( x => GetPublicEvents ( x ) . Any ( ) ) ;
110
+ if ( parentWithEvents == null )
111
+ continue ;
112
+
113
+ type . Parent = new ParentInfo { Name = parentWithEvents . FullName } ;
114
+ }
115
+
116
+ return namespaceData ;
117
+ }
118
+
119
+ private static IEnumerable < TypeDefinition > GetParents ( TypeDefinition type )
120
+ {
121
+ var current = type . BaseType != null && type . BaseType . ToString ( ) != "System.Object"
122
+ ? type . BaseType . Resolve ( )
123
+ : null ;
124
+
125
+ while ( current != null )
126
+ {
127
+ yield return current . Resolve ( ) ;
128
+
129
+ current = current . BaseType != null
130
+ ? current . BaseType . Resolve ( )
131
+ : null ;
132
+ }
133
+ }
134
+ }
135
+ }
0 commit comments