@@ -28,104 +28,106 @@ public override bool WillProcess(ICompiledAssembly compiledAssembly)
2828
2929 public override ILPostProcessResult Process ( ICompiledAssembly compiledAssembly )
3030 {
31- var logger = new ILPostProcessorLogger ( new List < DiagnosticMessage > ( ) ) ;
3231 using var resolver = new PostProcessorAssemblyResolver ( compiledAssembly . References ) ;
3332 using var assembly = compiledAssembly . LoadAssembly ( resolver ) ;
34- var referenceAssemblies = compiledAssembly . LoadLibraryAssemblies ( resolver ) . ToArray ( ) ;
35- try
33+ var logger = assembly . CreateLogger ( ) ;
34+ logger . Info ( $ "process GenericSerializeReference on { assembly . Name . Name } ({ string . Join ( "," , compiledAssembly . References . Where ( r => r . StartsWith ( "Library" ) ) ) } )") ;
35+ var modified = Process ( compiledAssembly , assembly , resolver , logger ) ;
36+ if ( ! modified ) return new ILPostProcessResult ( null , logger . Messages ) ;
37+
38+ var pe = new MemoryStream ( ) ;
39+ var pdb = new MemoryStream ( ) ;
40+ var writerParameters = new WriterParameters
3641 {
37- var loggerAttributes = assembly . GetAttributesOf < GenericSerializeReferenceLoggerAttribute > ( ) ;
38- if ( loggerAttributes . Any ( ) ) logger . LogLevel = ( LogLevel ) loggerAttributes . First ( ) . ConstructorArguments [ 0 ] . Value ;
39- logger . Info ( $ "process GenericSerializeReference on { assembly . Name . Name } ({ string . Join ( "," , referenceAssemblies . Select ( r => r . Name . Name ) ) } )") ;
40- var allTypes = referenceAssemblies . Append ( assembly )
41- . Where ( asm => ! asm . Name . Name . StartsWith ( "Unity." )
42- && ! asm . Name . Name . StartsWith ( "UnityEditor." )
43- && ! asm . Name . Name . StartsWith ( "UnityEngine." )
44- )
45- . SelectMany ( asm => asm . MainModule . GetAllTypes ( ) )
46- ;
47- logger . Debug ( $ "all types: { string . Join ( ", " , allTypes . Select ( t => t . Name ) ) } ") ;
48- var typeTree = new TypeTree ( allTypes ) ;
49- logger . Debug ( $ "tree: { typeTree } ") ;
50- var modified = Process ( assembly . MainModule , typeTree , logger ) ;
51- if ( ! modified ) return new ILPostProcessResult ( null , logger . Messages ) ;
42+ SymbolWriterProvider = new PortablePdbWriterProvider ( ) , SymbolStream = pdb , WriteSymbols = true
43+ } ;
44+ assembly . Write ( pe , writerParameters ) ;
45+ // assembly.Write();
46+ var inMemoryAssembly = new InMemoryAssembly ( pe . ToArray ( ) , pdb . ToArray ( ) ) ;
47+ return new ILPostProcessResult ( inMemoryAssembly , logger . Messages ) ;
48+ }
5249
53- var pe = new MemoryStream ( ) ;
54- var pdb = new MemoryStream ( ) ;
55- var writerParameters = new WriterParameters
56- {
57- SymbolWriterProvider = new PortablePdbWriterProvider ( ) , SymbolStream = pdb , WriteSymbols = true
58- } ;
59- assembly . Write ( pe , writerParameters ) ;
60- // assembly.Write();
61- var inMemoryAssembly = new InMemoryAssembly ( pe . ToArray ( ) , pdb . ToArray ( ) ) ;
62- return new ILPostProcessResult ( inMemoryAssembly , logger . Messages ) ;
50+ private bool Process ( ICompiledAssembly compiledAssembly , AssemblyDefinition assembly , PostProcessorAssemblyResolver resolver , ILPostProcessorLogger logger )
51+ {
52+ var module = assembly . MainModule ;
53+ IReadOnlyList < AssemblyDefinition > referenceAssemblies = Array . Empty < AssemblyDefinition > ( ) ;
54+ TypeTree typeTree = null ;
55+
56+ try
57+ {
58+ return ProcessProperties ( ) ;
6359 }
6460 finally
6561 {
66- foreach ( var reference in referenceAssemblies ) reference . Dispose ( ) ;
62+ foreach ( var @ref in referenceAssemblies ) @ref . Dispose ( ) ;
6763 }
68- }
6964
70- private bool Process ( ModuleDefinition module , TypeTree typeTree , ILPostProcessorLogger logger )
71- {
72- var modified = false ;
73- foreach ( var ( type , property , attribute ) in
74- from type in module . GetAllTypes ( )
75- where type . IsClass && ! type . IsAbstract
76- from property in type . Properties . ToArray ( ) // able to change `Properties` during looping
77- from attribute in property . GetAttributesOf < GenericSerializeReferenceAttribute > ( )
78- select ( type , property , attribute )
79- )
65+ bool ProcessProperties ( )
8066 {
81- if ( property . GetMethod == null )
67+ var modified = false ;
68+ foreach ( var ( type , property , attribute ) in
69+ from type in module . GetAllTypes ( )
70+ where type . IsClass && ! type . IsAbstract
71+ from property in type . Properties . ToArray ( ) // able to change `Properties` during looping
72+ from attribute in property . GetAttributesOf < GenericSerializeReferenceAttribute > ( )
73+ select ( type , property , attribute )
74+ )
8275 {
83- logger . Warning ( $ "Cannot process on property { property } without getter") ;
84- continue ;
85- }
76+ if ( property . GetMethod == null )
77+ {
78+ logger . Warning ( $ "Cannot process on property { property } without getter") ;
79+ continue ;
80+ }
8681
87- if ( ! property . PropertyType . IsGenericInstance )
88- {
89- logger . Warning ( $ "Cannot process on property { property } with non-generic type { property . PropertyType . Name } ") ;
90- continue ;
91- }
82+ if ( ! property . PropertyType . IsGenericInstance )
83+ {
84+ logger . Warning ( $ "Cannot process on property { property } with non-generic type { property . PropertyType . Name } ") ;
85+ continue ;
86+ }
9287
93- TypeReference baseInterface ;
94- var mode = ( GenerateMode ) attribute . ConstructorArguments [ 1 ] . Value ;
95- if ( mode == GenerateMode . Embed )
96- {
97- var wrapperName = $ "<{ property . Name } >__generic_serialize_reference";
98- var wrapper = property . DeclaringType . CreateNestedStaticPrivateClass ( wrapperName ) ;
99- baseInterface = CreateInterface ( wrapper ) ;
100- CreateDerivedClasses ( property , wrapper , baseInterface ) ;
101- }
102- else
103- {
104- baseInterface = module . ImportReference ( typeof ( IBase ) ) ;
105- }
88+ TypeReference baseInterface ;
89+ var mode = ( GenerateMode ) attribute . ConstructorArguments [ 1 ] . Value ;
90+ if ( mode == GenerateMode . Embed )
91+ {
92+ var wrapperName = $ "<{ property . Name } >__generic_serialize_reference";
93+ var wrapper = property . DeclaringType . CreateNestedStaticPrivateClass ( wrapperName ) ;
94+ baseInterface = CreateInterface ( wrapper ) ;
95+ CreateDerivedClasses ( property , wrapper , baseInterface ) ;
96+ }
97+ else
98+ {
99+ baseInterface = module . ImportReference ( typeof ( IBase ) ) ;
100+ }
106101
107- logger . Info ( $ "generate nested class with interface { baseInterface . FullName } ") ;
108- var fieldNamePrefix = ( string ) attribute . ConstructorArguments [ 0 ] . Value ;
109- GenerateField ( module , property , baseInterface , fieldNamePrefix ) ;
102+ logger . Info ( $ "generate nested class with interface { baseInterface . FullName } ") ;
103+ var fieldNamePrefix = ( string ) attribute . ConstructorArguments [ 0 ] . Value ;
104+ GenerateField ( module , property , baseInterface , fieldNamePrefix ) ;
110105
111- modified = true ;
106+ modified = true ;
107+ }
108+ return modified ;
112109 }
113- return modified ;
114110
115- TypeDefinition CreateInterface ( TypeDefinition wrapper , string interfaceName = "IBase" )
111+ void CreateTypeTree ( )
116112 {
117- // .class interface nested public abstract auto ansi
118- var interfaceAttributes = TypeAttributes . Class |
119- TypeAttributes . Interface |
120- TypeAttributes . NestedPublic |
121- TypeAttributes . Abstract ;
122- var baseInterface = new TypeDefinition ( "" , interfaceName , interfaceAttributes ) ;
123- wrapper . NestedTypes . Add ( baseInterface ) ;
124- return baseInterface ;
113+ if ( typeTree != null ) return ;
114+
115+ referenceAssemblies = compiledAssembly . LoadLibraryAssemblies ( resolver ) . ToArray ( ) ;
116+ var allTypes = referenceAssemblies . Append ( assembly )
117+ . Where ( asm => ! asm . Name . Name . StartsWith ( "Unity." )
118+ && ! asm . Name . Name . StartsWith ( "UnityEditor." )
119+ && ! asm . Name . Name . StartsWith ( "UnityEngine." )
120+ )
121+ . SelectMany ( asm => asm . MainModule . GetAllTypes ( ) )
122+ ;
123+ logger . Debug ( $ "all types: { string . Join ( ", " , allTypes . Select ( t => t . Name ) ) } ") ;
124+ typeTree = new TypeTree ( allTypes ) ;
125+ logger . Debug ( $ "tree: { typeTree } ") ;
125126 }
126127
127128 void CreateDerivedClasses ( PropertyDefinition property , TypeDefinition wrapper , TypeReference baseInterface )
128129 {
130+ if ( typeTree == null ) CreateTypeTree ( ) ;
129131 logger . Debug ( $ "get derived { property . PropertyType . Module } { property . PropertyType } { property . PropertyType . Resolve ( ) } ") ;
130132 foreach ( var derived in typeTree . GetOrCreateAllDerivedReference ( property . PropertyType ) )
131133 {
@@ -151,7 +153,19 @@ void CreateDerivedClasses(PropertyDefinition property, TypeDefinition wrapper, T
151153 }
152154 }
153155
154- internal static void GenerateField (
156+ private TypeDefinition CreateInterface ( TypeDefinition wrapper , string interfaceName = "IBase" )
157+ {
158+ // .class interface nested public abstract auto ansi
159+ var interfaceAttributes = TypeAttributes . Class |
160+ TypeAttributes . Interface |
161+ TypeAttributes . NestedPublic |
162+ TypeAttributes . Abstract ;
163+ var baseInterface = new TypeDefinition ( "" , interfaceName , interfaceAttributes ) ;
164+ wrapper . NestedTypes . Add ( baseInterface ) ;
165+ return baseInterface ;
166+ }
167+
168+ private static void GenerateField (
155169 ModuleDefinition module ,
156170 PropertyDefinition property ,
157171 TypeReference fieldType ,
@@ -162,7 +176,7 @@ internal static void GenerateField(
162176 InjectSetter ( property , serializedField ) ;
163177 }
164178
165- internal static FieldDefinition CreateSerializeReferenceField (
179+ private static FieldDefinition CreateSerializeReferenceField (
166180 ModuleDefinition module ,
167181 PropertyDefinition property ,
168182 TypeReference @interface ,
@@ -183,7 +197,7 @@ internal static FieldDefinition CreateSerializeReferenceField(
183197 return serializedField ;
184198 }
185199
186- internal static void InjectGetter ( PropertyDefinition property , FieldDefinition serializedField )
200+ private static void InjectGetter ( PropertyDefinition property , FieldDefinition serializedField )
187201 {
188202 // --------add--------
189203 // IL_0000: ldarg.0 // this
@@ -206,7 +220,7 @@ internal static void InjectGetter(PropertyDefinition property, FieldDefinition s
206220 instructions . Insert ( 4 , Instruction . Create ( OpCodes . Pop ) ) ;
207221 }
208222
209- internal static void InjectSetter ( PropertyDefinition property , FieldDefinition serializedField )
223+ private static void InjectSetter ( PropertyDefinition property , FieldDefinition serializedField )
210224 {
211225 //IL_0000: ldarg.0 // this
212226 //IL_0001: ldarg.1 // 'value'
0 commit comments