There have been a number of posts lately about downloading assemblies in the background. So tonight I decided to try and work up a sample. I hit a few roadblocks, though. The main one is the failure of Assembly.Load to actually load the assembly.
So, I was able to download the assemblies just fine using the downloader, and I have the code in place to do everything I need to do with them to get them on the canvas. However, calling Assembly.Load on the assembly (whether I just force it local or actually
download it), resulted in a System.MethodAccessException on Assembly.Load(assemblyname).
"Attempt to access the method failed: System.Reflection.Assembly.LoadFrom(System.String)"
That seemed like a really an odd exception to get back given its usual interpretation, so I googled and managed to find
this thread which I completely missed the first time around:
From reading the referenced articles (like
this one), I have to conclude that Assembly.Load(string) is considered critical and therefore, despite being exposed, is not something we can call from our application code. Sure enough, after loading it up in Reflector, I see it is indeed marked as such:
Unless that changes and Assembly.Load is made SafeCritical, or a SafeCritical alternative is provided, it destroys the idea of background downloading assemblies and having a real componentized or plugin-style application model.
Pete
Developer Community Program Manager - XAML, WPF, Silverlight, .NETMF/Gadgeteer
10rem.net - Pete Brown's site and blog | twitter: @pete_brown
I work for the Developer Guidance group in Microsoft. Opinions are my own.
As far as I can see, the only (non-adequate) alternative is to write an HTTP handler which will emit XAML, which will reference needed assemblies. I.e. to perform selection of assemblies to load on server and not on client.
-- Yuri Zholobov, [MCPD:EAD, MCPID 3749109], MS Team
If I understand what you're suggesting, that won't work, as other than the main assembly specified in x:Class, the other assemblies are all downloaded due to their inclusion in the manifest of the main assembly.
Interesting idea, though :)
Pete
Developer Community Program Manager - XAML, WPF, Silverlight, .NETMF/Gadgeteer
10rem.net - Pete Brown's site and blog | twitter: @pete_brown
I work for the Developer Guidance group in Microsoft. Opinions are my own.
Thanks for trying this. I was one of the guys thinking about this incremental load idea. This must be something slated for the final release...there's no way you could build a RIA of any substance and not do incremental loading
Thanks again!
---
Phil Cockfield
twitter: @philcockfield
blog: http://TestHarness.org
Then iterate Children of the canvas and you will get your loaded plugins. I tried this and just copied the Plugin1.dll from totally different (but of course SL)project with no references. So you need just text xmlns:plugin1="clr-namespace:Plugin1;assembly=ClientBin/Plugin1.dll"
in your XAML and corresponding file in your ClientBin. I have working sample which works, if you need it.
-- Yuri Zholobov, [MCPD:EAD, MCPID 3749109], MS Team
Just to correct you all, you can load assemblies downloaded with the Downloader class and then load them. I'm doing it now. I've made a plugins library if anyone wishes to check it out?
It definitely does work (although I did just have a quick panic when I realised I was actually referencing the plugins from the main project since I was too lazy to copy them to the ClientBin folder everytime, but I just unreferenced them and did a test
copying them manually)
The plugins have to be in the ClientBin in order to allow them to be loaded is the one stipulation I have discovered.
Psychlist1972
Contributor
6802 Points
1079 Posts
Microsoft
Moderator
Plugins, Reflection, the Downloader object and SecurityCritical code
Nov 09, 2007 05:12 AM | LINK
Hi All
There have been a number of posts lately about downloading assemblies in the background. So tonight I decided to try and work up a sample. I hit a few roadblocks, though. The main one is the failure of Assembly.Load to actually load the assembly.
So, I was able to download the assemblies just fine using the downloader, and I have the code in place to do everything I need to do with them to get them on the canvas. However, calling Assembly.Load on the assembly (whether I just force it local or actually download it), resulted in a System.MethodAccessException on Assembly.Load(assemblyname).
"Attempt to access the method failed: System.Reflection.Assembly.LoadFrom(System.String)"
That seemed like a really an odd exception to get back given its usual interpretation, so I googled and managed to find this thread which I completely missed the first time around:
From reading the referenced articles (like this one), I have to conclude that Assembly.Load(string) is considered critical and therefore, despite being exposed, is not something we can call from our application code. Sure enough, after loading it up in Reflector, I see it is indeed marked as such:
[SecurityCritical] public static Assembly Load(AssemblyName assemblyRef) { StackCrawlMark lookForMyCaller = StackCrawlMark.LookForMyCaller; return InternalLoad(assemblyRef, null, ref lookForMyCaller, false); }Unless that changes and Assembly.Load is made SafeCritical, or a SafeCritical alternative is provided, it destroys the idea of background downloading assemblies and having a real componentized or plugin-style application model.
Pete
10rem.net - Pete Brown's site and blog | twitter: @pete_brown
I work for the Developer Guidance group in Microsoft. Opinions are my own.
Yuri Zholobov
Member
270 Points
77 Posts
Re: Plugins, Reflection, the Downloader object and SecurityCritical code
Nov 09, 2007 05:26 AM | LINK
As far as I can see, the only (non-adequate) alternative is to write an HTTP handler which will emit XAML, which will reference needed assemblies. I.e. to perform selection of assemblies to load on server and not on client.
Psychlist1972
Contributor
6802 Points
1079 Posts
Microsoft
Moderator
Re: Plugins, Reflection, the Downloader object and SecurityCritical code
Nov 09, 2007 05:34 AM | LINK
If I understand what you're suggesting, that won't work, as other than the main assembly specified in x:Class, the other assemblies are all downloaded due to their inclusion in the manifest of the main assembly.
Interesting idea, though :)
Pete
10rem.net - Pete Brown's site and blog | twitter: @pete_brown
I work for the Developer Guidance group in Microsoft. Opinions are my own.
philjones
Member
83 Points
201 Posts
Re: Plugins, Reflection, the Downloader object and SecurityCritical code
Nov 09, 2007 07:25 AM | LINK
Pete,
Thanks for trying this. I was one of the guys thinking about this incremental load idea. This must be something slated for the final release...there's no way you could build a RIA of any substance and not do incremental loading
Thanks again!
Phil Cockfield
twitter: @philcockfield
blog: http://TestHarness.org
Yuri Zholobov
Member
270 Points
77 Posts
Re: Plugins, Reflection, the Downloader object and SecurityCritical code
Nov 09, 2007 07:31 AM | LINK
Not at all. Do not use x:Class, use xmlns with clr-namespace like this:
<Canvas x:Name="parentCanvas"
xmlns="http://schemas.microsoft.com/client/2007"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Loaded="Page_Loaded"
x:Class="SilverlightProject1.Page;assembly=ClientBin/SilverlightProject1.dll"
xmlns:plugin1="clr-namespace:Plugin1;assembly=ClientBin/Plugin1.dll"
Width="640"
Height="480"
Background="White"
>
<TextBlock x:Name="tbLog" Canvas.Left="0" Canvas.Top="0" Width="640" Height="480" />
<plugin1:Page />
</Canvas>
Then iterate Children of the canvas and you will get your loaded plugins. I tried this and just copied the Plugin1.dll from totally different (but of course SL)project with no references. So you need just text xmlns:plugin1="clr-namespace:Plugin1;assembly=ClientBin/Plugin1.dll" in your XAML and corresponding file in your ClientBin. I have working sample which works, if you need it.
damoxc
Member
90 Points
46 Posts
Re: Re: Plugins, Reflection, the Downloader object and SecurityCritical code
Nov 09, 2007 10:34 AM | LINK
Just to correct you all, you can load assemblies downloaded with the Downloader class and then load them. I'm doing it now. I've made a plugins library if anyone wishes to check it out?
Yuri Zholobov
Member
270 Points
77 Posts
Re: Re: Plugins, Reflection, the Downloader object and SecurityCritical code
Nov 09, 2007 10:38 AM | LINK
It would be interesting if you show key lines of code which loads a downloaded assembly.
damoxc
Member
90 Points
46 Posts
Re: Re: Re: Plugins, Reflection, the Downloader object and SecurityCritical code
Nov 09, 2007 10:40 AM | LINK
http://svn.digitalnetworks.co.uk/trunk/utilis/Utilis.Plugins/PluginDownloader.cs
It's open source.
Yuri Zholobov
Member
270 Points
77 Posts
Re: Re: Re: Plugins, Reflection, the Downloader object and SecurityCritical code
Nov 09, 2007 10:46 AM | LINK
Thats strange. This directly contradicts what Psychlist1972 says about Assembly.Load excpetion.
damoxc
Member
90 Points
46 Posts
Re: Re: Re: Re: Plugins, Reflection, the Downloader object and SecurityCritical code
Nov 09, 2007 10:57 AM | LINK
It definitely does work (although I did just have a quick panic when I realised I was actually referencing the plugins from the main project since I was too lazy to copy them to the ClientBin folder everytime, but I just unreferenced them and did a test copying them manually)
The plugins have to be in the ClientBin in order to allow them to be loaded is the one stipulation I have discovered.