11using System ;
22using System . Collections . Generic ;
33using System . Linq ;
4+ using System . Reflection ;
45using dnlib . DotNet ;
56using dnlib . DotNet . Emit ;
67
@@ -59,10 +60,9 @@ static FieldDefUser Clone(FieldDef origin) {
5960 /// <returns>The new TypeDef.</returns>
6061 static TypeDef PopulateContext ( TypeDef typeDef , InjectContext ctx ) {
6162 TypeDef ret ;
62- IDnlibDef existing ;
63- if ( ! ctx . Map . TryGetValue ( typeDef , out existing ) ) {
63+ if ( ! ctx . MemberMap . TryGetValue ( typeDef , out var existing ) ) {
6464 ret = Clone ( typeDef ) ;
65- ctx . Map [ typeDef ] = ret ;
65+ ctx . MemberMap [ typeDef ] = ret ;
6666 }
6767 else
6868 ret = ( TypeDef ) existing ;
@@ -71,10 +71,10 @@ static TypeDef PopulateContext(TypeDef typeDef, InjectContext ctx) {
7171 ret . NestedTypes . Add ( PopulateContext ( nestedType , ctx ) ) ;
7272
7373 foreach ( MethodDef method in typeDef . Methods )
74- ret . Methods . Add ( ( MethodDef ) ( ctx . Map [ method ] = Clone ( method ) ) ) ;
74+ ret . Methods . Add ( ( MethodDef ) ( ctx . MemberMap [ method ] = Clone ( method ) ) ) ;
7575
7676 foreach ( FieldDef field in typeDef . Fields )
77- ret . Fields . Add ( ( FieldDef ) ( ctx . Map [ field ] = Clone ( field ) ) ) ;
77+ ret . Fields . Add ( ( FieldDef ) ( ctx . MemberMap [ field ] = Clone ( field ) ) ) ;
7878
7979 return ret ;
8080 }
@@ -85,12 +85,12 @@ static TypeDef PopulateContext(TypeDef typeDef, InjectContext ctx) {
8585 /// <param name="typeDef">The origin TypeDef.</param>
8686 /// <param name="ctx">The injection context.</param>
8787 static void CopyTypeDef ( TypeDef typeDef , InjectContext ctx ) {
88- var newTypeDef = ( TypeDef ) ctx . Map [ typeDef ] ;
88+ var newTypeDef = ( TypeDef ) ctx . MemberMap [ typeDef ] ;
8989
90- newTypeDef . BaseType = ( ITypeDefOrRef ) ctx . Importer . Import ( typeDef . BaseType ) ;
90+ newTypeDef . BaseType = ctx . Importer . Import ( typeDef . BaseType ) ;
9191
9292 foreach ( InterfaceImpl iface in typeDef . Interfaces )
93- newTypeDef . Interfaces . Add ( new InterfaceImplUser ( ( ITypeDefOrRef ) ctx . Importer . Import ( iface . Interface ) ) ) ;
93+ newTypeDef . Interfaces . Add ( new InterfaceImplUser ( ctx . Importer . Import ( iface . Interface ) ) ) ;
9494 }
9595
9696 /// <summary>
@@ -99,7 +99,7 @@ static void CopyTypeDef(TypeDef typeDef, InjectContext ctx) {
9999 /// <param name="methodDef">The origin MethodDef.</param>
100100 /// <param name="ctx">The injection context.</param>
101101 static void CopyMethodDef ( MethodDef methodDef , InjectContext ctx ) {
102- var newMethodDef = ( MethodDef ) ctx . Map [ methodDef ] ;
102+ var newMethodDef = ( MethodDef ) ctx . MemberMap [ methodDef ] ;
103103
104104 newMethodDef . Signature = ctx . Importer . Import ( methodDef . Signature ) ;
105105 newMethodDef . Parameters . UpdateParameterTypes ( ) ;
@@ -151,7 +151,7 @@ static void CopyMethodDef(MethodDef methodDef, InjectContext ctx) {
151151
152152 foreach ( ExceptionHandler eh in methodDef . Body . ExceptionHandlers )
153153 newMethodDef . Body . ExceptionHandlers . Add ( new ExceptionHandler ( eh . HandlerType ) {
154- CatchType = eh . CatchType == null ? null : ( ITypeDefOrRef ) ctx . Importer . Import ( eh . CatchType ) ,
154+ CatchType = eh . CatchType == null ? null : ctx . Importer . Import ( eh . CatchType ) ,
155155 TryStart = ( Instruction ) bodyMap [ eh . TryStart ] ,
156156 TryEnd = ( Instruction ) bodyMap [ eh . TryEnd ] ,
157157 HandlerStart = ( Instruction ) bodyMap [ eh . HandlerStart ] ,
@@ -169,7 +169,7 @@ static void CopyMethodDef(MethodDef methodDef, InjectContext ctx) {
169169 /// <param name="fieldDef">The origin FieldDef.</param>
170170 /// <param name="ctx">The injection context.</param>
171171 static void CopyFieldDef ( FieldDef fieldDef , InjectContext ctx ) {
172- var newFieldDef = ( FieldDef ) ctx . Map [ fieldDef ] ;
172+ var newFieldDef = ( FieldDef ) ctx . MemberMap [ fieldDef ] ;
173173
174174 newFieldDef . Signature = ctx . Importer . Import ( fieldDef . Signature ) ;
175175 }
@@ -192,8 +192,8 @@ static void Copy(TypeDef typeDef, InjectContext ctx, bool copySelf) {
192192
193193 foreach ( FieldDef field in typeDef . Fields )
194194 CopyFieldDef ( field , ctx ) ;
195- }
196-
195+ }
196+
197197 /// <summary>
198198 /// Injects the specified TypeDef to another module.
199199 /// </summary>
@@ -204,9 +204,22 @@ public static TypeDef Inject(TypeDef typeDef, ModuleDef target) {
204204 var ctx = new InjectContext ( typeDef . Module , target ) ;
205205 PopulateContext ( typeDef , ctx ) ;
206206 Copy ( typeDef , ctx , true ) ;
207- return ( TypeDef ) ctx . Map [ typeDef ] ;
208- }
209-
207+ return ( TypeDef ) ctx . MemberMap [ typeDef ] ;
208+ }
209+
210+ /// <summary>
211+ /// Imports a <see cref="MethodBase"/> as a <see cref="IMethod"/>. This will be either
212+ /// a <see cref="MemberRef"/> or a <see cref="MethodSpec"/>.
213+ /// </summary>
214+ /// <param name="source">The source module.</param>
215+ /// <param name="methodBase">The method</param>
216+ /// <returns>The imported method or <c>null</c> if <paramref name="methodBase"/> is invalid
217+ /// or if we failed to import the method</returns>
218+ public static IMethod Import ( ModuleDef target , MethodBase methodBase ) {
219+ var ctx = new InjectContext ( null , target ) ;
220+ return ctx . Importer . Import ( methodBase ) ;
221+ }
222+
210223 /// <summary>
211224 /// Injects the specified MethodDef to another module.
212225 /// </summary>
@@ -215,9 +228,9 @@ public static TypeDef Inject(TypeDef typeDef, ModuleDef target) {
215228 /// <returns>The injected MethodDef.</returns>
216229 public static MethodDef Inject ( MethodDef methodDef , ModuleDef target ) {
217230 var ctx = new InjectContext ( methodDef . Module , target ) ;
218- ctx . Map [ methodDef ] = Clone ( methodDef ) ;
231+ ctx . MemberMap [ methodDef ] = Clone ( methodDef ) ;
219232 CopyMethodDef ( methodDef , ctx ) ;
220- return ( MethodDef ) ctx . Map [ methodDef ] ;
233+ return ( MethodDef ) ctx . MemberMap [ methodDef ] ;
221234 }
222235
223236 /// <summary>
@@ -229,20 +242,20 @@ public static MethodDef Inject(MethodDef methodDef, ModuleDef target) {
229242 /// <returns>Injected members.</returns>
230243 public static IEnumerable < IDnlibDef > Inject ( TypeDef typeDef , TypeDef newType , ModuleDef target ) {
231244 var ctx = new InjectContext ( typeDef . Module , target ) ;
232- ctx . Map [ typeDef ] = newType ;
245+ ctx . MemberMap [ typeDef ] = newType ;
233246 PopulateContext ( typeDef , ctx ) ;
234247 Copy ( typeDef , ctx , false ) ;
235- return ctx . Map . Values . Except ( new [ ] { newType } ) ;
248+ return ctx . MemberMap . Values . Except ( new [ ] { newType } ) . OfType < IDnlibDef > ( ) ;
236249 }
237250
238251 /// <summary>
239252 /// Context of the injection process.
240253 /// </summary>
241- class InjectContext : ImportResolver {
254+ class InjectContext : ImportMapper {
242255 /// <summary>
243256 /// The mapping of origin definitions to injected definitions.
244257 /// </summary>
245- public readonly Dictionary < IDnlibDef , IDnlibDef > Map = new Dictionary < IDnlibDef , IDnlibDef > ( ) ;
258+ public readonly Dictionary < object , IMemberRef > MemberMap = new Dictionary < object , IMemberRef > ( ) ;
246259
247260 /// <summary>
248261 /// The module which source type originated from.
@@ -259,6 +272,10 @@ class InjectContext : ImportResolver {
259272 /// </summary>
260273 readonly Importer importer ;
261274
275+ private readonly AssemblyRef netstandardRef ;
276+ private readonly AssemblyRef mscorlibRef ;
277+ private readonly AssemblyRef corelibRef ;
278+
262279 /// <summary>
263280 /// Initializes a new instance of the <see cref="InjectContext" /> class.
264281 /// </summary>
@@ -267,8 +284,11 @@ class InjectContext : ImportResolver {
267284 public InjectContext ( ModuleDef module , ModuleDef target ) {
268285 OriginModule = module ;
269286 TargetModule = target ;
270- importer = new Importer ( target , ImporterOptions . TryToUseTypeDefs ) ;
271- importer . Resolver = this ;
287+ importer = new Importer ( target , ImporterOptions . TryToUseTypeDefs , new GenericParamContext ( ) , this ) ;
288+
289+ netstandardRef = TryResolveAssembly ( "netstandard" ) ;
290+ mscorlibRef = TryResolveAssembly ( "mscorlib" ) ;
291+ corelibRef = TryResolveAssembly ( "System.Private.CoreLib" ) ;
272292 }
273293
274294 /// <summary>
@@ -277,27 +297,131 @@ public InjectContext(ModuleDef module, ModuleDef target) {
277297 /// <value>The importer.</value>
278298 public Importer Importer {
279299 get { return importer ; }
280- }
300+ }
301+
302+ /// <inheritdoc />
303+ public override ITypeDefOrRef Map ( ITypeDefOrRef source ) {
304+ if ( MemberMap . TryGetValue ( source , out var result ) )
305+ return ( ITypeDefOrRef ) result ;
306+
307+ //HACK: for netcore
308+ //System.Enviroment and System.AppDomain is in System.Runtime.Extensions/mscorlib/netstandard
309+ //System.Runtime.InteropServices.Marshal is in System.Runtime.InteropServices/mscorlib/netstandard
310+ if ( source . IsTypeRef && OriginModule ? . CorLibTypes . AssemblyRef != TargetModule . CorLibTypes . AssemblyRef ) {
311+ var sourceRef = ( TypeRef ) source ;
312+ TypeRef destRef = TryResolveType ( sourceRef , TargetModule . CorLibTypes . AssemblyRef , false ) ??
313+ TryResolveType ( sourceRef , netstandardRef , true ) ??
314+ TryResolveType ( sourceRef , mscorlibRef , true ) ??
315+ TryResolveType ( sourceRef , TryResolveAssembly ( sourceRef . DefinitionAssembly . Name ) , false ) ??
316+ TryResolveType ( sourceRef , corelibRef , false ) ;
317+
318+ if ( destRef != null ) {
319+ var stack = new Stack < IMDTokenProvider > ( 2 ) ;
320+ stack . Push ( destRef ) ;
321+ TypeRef cur = destRef ;
322+ do {
323+ var scope = cur . ResolutionScope ;
324+ stack . Push ( scope ) ;
325+ cur = scope as TypeRef ;
326+ } while ( cur != null ) ;
327+ do {
328+ TargetModule . UpdateRowId ( stack . Pop ( ) ) ;
329+ } while ( stack . Count > 0 ) ;
330+ }
331+
332+ MemberMap [ source ] = destRef ;
333+ return destRef ;
334+ }
281335
336+ return null ;
337+ }
338+
339+ TypeRef TryResolveType ( TypeRef sourceRef , AssemblyRef scope , bool followForward ) {
340+ if ( scope == null )
341+ return null ;
342+
343+ var typeRef = Import2 ( sourceRef , scope ) ;
344+
345+ var scopeDef = TargetModule . Context . AssemblyResolver . Resolve ( typeRef . DefinitionAssembly , TargetModule ) ;
346+ if ( scopeDef != null ) {
347+ if ( scopeDef . TypeExists ( typeRef ) )
348+ return typeRef ;
349+ var sigComparer = new SigComparer ( SigComparerOptions . DontCompareTypeScope ) ;
350+ var exportType = scopeDef . Modules . SelectMany ( m => m . ExportedTypes ) . Where ( et => sigComparer . Equals ( et , typeRef ) ) . FirstOrDefault ( ) ;
351+ if ( exportType != null ) {
352+ if ( followForward && ( corelibRef == null || exportType . Implementation . Name != corelibRef . Name ) )
353+ return exportType . ToTypeRef ( ) ;
354+ else
355+ return typeRef ;
356+ }
357+ }
358+
359+ return null ;
360+ }
361+
362+ AssemblyRef TryResolveAssembly ( UTF8String name ) {
363+ return TargetModule . GetAssemblyRef ( name ) ?? TargetModule . Context . AssemblyResolver . Resolve ( new AssemblyRefUser ( name ) , TargetModule ) . ToAssemblyRef ( ) ;
364+ }
365+
366+ TypeRef Import2 ( TypeRef type , IResolutionScope scope ) {
367+ if ( type is null )
368+ return null ;
369+ TypeRef result ;
370+
371+ var declaringType = type . DeclaringType ;
372+ if ( ! ( declaringType is null ) )
373+ result = new TypeRefUser ( TargetModule , type . Namespace , type . Name , Import2 ( declaringType , scope ) ) ;
374+ else
375+ result = new TypeRefUser ( TargetModule , type . Namespace , type . Name , scope ) ;
376+
377+ return result ;
378+ }
379+
282380 /// <inheritdoc />
283- public override TypeDef Resolve ( TypeDef typeDef ) {
284- if ( Map . ContainsKey ( typeDef ) )
285- return ( TypeDef ) Map [ typeDef ] ;
381+ public override IMethod Map ( MethodDef source ) {
382+ if ( MemberMap . TryGetValue ( source , out var result ) )
383+ return ( MethodDef ) result ;
286384 return null ;
287385 }
288386
289387 /// <inheritdoc />
290- public override MethodDef Resolve ( MethodDef methodDef ) {
291- if ( Map . ContainsKey ( methodDef ) )
292- return ( MethodDef ) Map [ methodDef ] ;
388+ public override IField Map ( FieldDef source ) {
389+ if ( MemberMap . ContainsKey ( source ) )
390+ return ( FieldDef ) MemberMap [ source ] ;
293391 return null ;
294392 }
295393
296- /// <inheritdoc />
297- public override FieldDef Resolve ( FieldDef fieldDef ) {
298- if ( Map . ContainsKey ( fieldDef ) )
299- return ( FieldDef ) Map [ fieldDef ] ;
300- return null ;
394+ public override TypeRef Map ( Type source ) {
395+ if ( MemberMap . TryGetValue ( source , out var result ) )
396+ return ( TypeRef ) result ;
397+
398+ if ( OriginModule ? . CorLibTypes . AssemblyRef != TargetModule . CorLibTypes . AssemblyRef ) {
399+ var sourceRef = ( TypeRef ) TargetModule . Import ( source ) ;
400+ TypeRef destRef = TryResolveType ( sourceRef , TargetModule . CorLibTypes . AssemblyRef , false ) ??
401+ TryResolveType ( sourceRef , netstandardRef , true ) ??
402+ TryResolveType ( sourceRef , mscorlibRef , true ) ??
403+ TryResolveType ( sourceRef , TryResolveAssembly ( sourceRef . DefinitionAssembly . Name ) , false ) ??
404+ TryResolveType ( sourceRef , corelibRef , false ) ;
405+
406+ if ( destRef != null ) {
407+ var stack = new Stack < IMDTokenProvider > ( 2 ) ;
408+ stack . Push ( destRef ) ;
409+ TypeRef cur = destRef ;
410+ do {
411+ var scope = cur . ResolutionScope ;
412+ stack . Push ( scope ) ;
413+ cur = scope as TypeRef ;
414+ } while ( cur != null ) ;
415+ do {
416+ TargetModule . UpdateRowId ( stack . Pop ( ) ) ;
417+ } while ( stack . Count > 0 ) ;
418+
419+ MemberMap [ source ] = destRef ;
420+ return destRef ;
421+ }
422+ }
423+
424+ return null ;
301425 }
302426 }
303427 }
0 commit comments