Answered by:
Resolving portable library assemblies

Question
-
Hello,
I am using the AppDomain.AssemblyResolve (in a full profile 4.5 assembly) to help resolving some of the requested assemblies. However, if I return a portable library assembly in this handler, I am asked about the portable library itsef, eg. I am asked to resolve System, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e, Retargetable=Yes.
What should I return?
(I obviously cannot use Assembly.Load(args.Name) because that would put me in an infinite loop for assemblies I am unable to resolve.)
Thanks,
Jan- Edited by Jan Kučera Monday, September 3, 2012 11:51 PM
Monday, September 3, 2012 11:51 PM
Answers
-
I tried to reproduce this but I never got asked to resolve System, Version=2.0.5.0, it automatically loads System, Version=4.0.0.0.
"The best I came up until now was to remember last requested assembly and try Assembly.Load in the resolve event handler, to prevent stack overflow."
Can't you remove the Resolve event, call Assembly.Load and then put back the Resolve event?
"Also, I obviously return full framework assemblies where the portable subset is being asked, which works in my case now, but I guess there is no guarantee it will work in other cases too..."
Actually you must return a full framework assembly, you can't load version 2.0.5.0 of System in .NET 4.5! In general you can't load 2 different versions of any of the System.* assemblies. If you do try to call Assembl.Load with version 2.0.5.0 a 4.0 assembly will be returned instead.
- Marked as answer by Jan Kučera Thursday, September 6, 2012 9:15 AM
Tuesday, September 4, 2012 2:17 PM -
"the problem is how to detect that I am asked to resolve a portable library assembly"
You can use AssemblyName to parse the requested assembly name and check the Flags property for AssemblyNameFlags.Retargetable.
"or more generally, that I am asked to resolve an assembly that Assembly.Load would succeed loading. "
The problem is that this situation should not happen, Resolve is the last thing CLR tries when loading an assembly, it is only raised if all other attempts failed (load from GAC, load from appdomain base dir etc.). Also, it is recommended that Resolve should return null if it doesn't recognize an assembly, have you tried to do that for such assemblies?
- Marked as answer by Jan Kučera Thursday, September 6, 2012 9:15 AM
Tuesday, September 4, 2012 2:51 PM
All replies
-
Hi Jan,
Thank you for posting on this forum.
Please try this code:
Private Shared Function MyResolveEventHandler(sender As Object, args As ResolveEventArgs) As Assembly Console.WriteLine("Resolving...") Return GetType(MyType).Assembly End Function 'MyResolveEventHandler
I copy it here: http://msdn.microsoft.com/en-us/library/system.appdomain.assemblyresolve.aspx
I hope it is helpful.
Best regards,
Mike Feng
MSDN Community Support | Feedback to us
Please remember to mark the replies as answers if they help and unmark them if they provide no help.
Tuesday, September 4, 2012 10:07 AM -
Hello Mike,
Thank you for your reply. The code does in advance know what type it will be asked for, so the example is just to show the syntax, otherwise not really helpful. The trick seems to be find out what to return. The best I came up until now was to remember last requested assembly and try Assembly.Load in the resolve event handler, to prevent stack overflow.
This works, but I am not sure this is the best solution. Also, I obviously return full framework assemblies where the portable subset is being asked, which works in my case now, but I guess there is no guarantee it will work in other cases too...
Jan
Tuesday, September 4, 2012 10:18 AM -
Hi Jan,
Please check out this thread:
http://sandcastle.codeplex.com/discussions/268713
Regards, http://www.shwetalodha.blogspot.in/
Tuesday, September 4, 2012 11:54 AM -
Hi Jan,
When you use the Portable Class Library it will actually upgrade/update your .net assemblies on disk in order to use this, which makes sense, and with out running the below installed mentioned above you will not be able to use any .net assembly which is based off the Portable Class Library.
http://www.microsoft.com/en-us/download/details.aspx?id=3556
Here is the complete post:
Regards, http://www.shwetalodha.blogspot.in/
- Proposed as answer by Shweta Jain (Lodha) Tuesday, September 4, 2012 11:55 AM
- Edited by Shweta Jain (Lodha) Tuesday, September 4, 2012 11:58 AM Added more content
Tuesday, September 4, 2012 11:55 AM -
Hi Shweta,
although the sandcastle people hit (probably) the same issue, they solved it by letting the resolver know ahead that they are looking for portable assemblies. Moreover, they do not need to actually execute the assemblies, so the reference folder is enough for them.
The other solution is unrelated. I am not getting FileLoadExceptions and already running on 4.5 (which means VS 2012), so no install is needed as noted there.
Jan
Tuesday, September 4, 2012 12:11 PM -
I tried to reproduce this but I never got asked to resolve System, Version=2.0.5.0, it automatically loads System, Version=4.0.0.0.
"The best I came up until now was to remember last requested assembly and try Assembly.Load in the resolve event handler, to prevent stack overflow."
Can't you remove the Resolve event, call Assembly.Load and then put back the Resolve event?
"Also, I obviously return full framework assemblies where the portable subset is being asked, which works in my case now, but I guess there is no guarantee it will work in other cases too..."
Actually you must return a full framework assembly, you can't load version 2.0.5.0 of System in .NET 4.5! In general you can't load 2 different versions of any of the System.* assemblies. If you do try to call Assembl.Load with version 2.0.5.0 a 4.0 assembly will be returned instead.
- Marked as answer by Jan Kučera Thursday, September 6, 2012 9:15 AM
Tuesday, September 4, 2012 2:17 PM -
Thanks Mike.
I could remove the Resolve event and add it later back, the problem is how to detect that I am asked to resolve a portable library assembly, or more generally, that I am asked to resolve an assembly that Assembly.Load would succeed loading. I could just try it each time and put it into try block, but is it the best way to check?
"Actually you must return a full framework assembly, you can't load version 2.0.5.0 of System in .NET 4.5! In general you can't load 2 different versions of any of the System.* assemblies. If you do try to call Assembl.Load with version 2.0.5.0 a 4.0 assembly will be returned instead."
Then I take it that it actually is guaranted. :-)
Jan
As for the repro, maybe you could try with the Assembly.Load(byte[]) overload to load a portable assembly.
Tuesday, September 4, 2012 2:31 PM -
"the problem is how to detect that I am asked to resolve a portable library assembly"
You can use AssemblyName to parse the requested assembly name and check the Flags property for AssemblyNameFlags.Retargetable.
"or more generally, that I am asked to resolve an assembly that Assembly.Load would succeed loading. "
The problem is that this situation should not happen, Resolve is the last thing CLR tries when loading an assembly, it is only raised if all other attempts failed (load from GAC, load from appdomain base dir etc.). Also, it is recommended that Resolve should return null if it doesn't recognize an assembly, have you tried to do that for such assemblies?
- Marked as answer by Jan Kučera Thursday, September 6, 2012 9:15 AM
Tuesday, September 4, 2012 2:51 PM -
The retargetable name part sounds like it would do, thanks!
Yes I did, if I return null, it throws a FileNotFoundException.
Thursday, September 6, 2012 9:14 AM