It's kind of disheartening when you look at User Solutions (which is how I'll refer to Sandboxed Solutions), especially if you're looking to use User Solutions to deliver some components that you're intending to hard-bake into a page layout (for instance).
Before I go any further explaining why, here's a nice short article giving a very brief overview of User Solutions from Wictor Wilen:
Ok, so off we go...
Recently I had an opportunity to look into User Solutions in more detail and found quite a few harsh limitations. My foray into this world came about while I was trying to add a Web Control into a page layout - i.e. hard-baked into the HTML. I had given myself the brief to use User Solutions to deliver all the code to see just how it could be achieved. Needless to say, after trying to add the assembly references into the page layout I tested the page, only to get an error stating that the assembly couldn't be found. Curious, I thought - so I tried and checked and re-checked my code and references to make sure I hadn't got it wrong but it was all to no avail. Then I read Wictor's article and found another article (http://www.elumenotion.com/Blog/Lists/Posts/Post.aspx?ID=109) which is when I had a moment of clarity and understanding.
It was an "of course" moment: user solutions run in their own process - the User Code Worker Process (a.k.a Sandbox Worker Process) outside of the IIS worker process. Pages are initially parsed by the IIS worker process and therefore any references to assemblies are also parsed at this point. Due to the way User Solution assemblies are used, the IIS worker process doesn't really know about them and therefore cannot resolve them - hence the error I was getting.
So that was that: but how can I add a Web Control that's delivered by User Solution into a page layout? Is it even possible? Well, in stepped the SPUserCodeWebPart. To be honest, despite doing the SharePoint 2010 exams, there was no mention of this component - nothing during my revision came up and highlighted this Web Part and yet, to me, it appears to be a fundamental part of the User Solution architecture.
Any way, putting that to one side, I implemented a test Web Part I had written: very simple "Hello world" example and added the necessary properties (Solution ID, Assembly Full Name, and the Type Full Name) to the SPUserCodeWebPart wrapper and there it was - it worked. The reason is works is because of the way the SPUserCodeWebPart makes a call out to the User Code Worker Process which loads DLLs from a separate location to those loaded by the IIS worker process. Each User Code assembly comes with its own web.config file declaring it as a Safe Control (which is why you cannot reference the assembly directly on the page as the IIS worker process knows nothing about these files). The wrapping SPUserCodeWebPart asks the User Code Worker Process to load the declared assembly and type from the specified solution: the work process looks to check the information and then loads the type against the subset of the Microsoft.SharePoint framework. Any errors it encounters, it pumps back up the pipeline.
But what about properties?, I thought. Well, these can also be passed as follows using the SPUserCodeProperty class:
In my Web Part I exposed a string property called "MyValue" and using the SPUserCodeProperty I set that to be "Some text". My Web Part then used that to output in HTML. Simple. Trying a more complex type I tried a custom enumeration passing in the value as my enumeration name and that also worked.
Before this success (which hadn't come about until the tail-end of my investigations) I had decided to try to get a Web Control to work. By it's name alone you can determine that the SPUserCodeWebPart is for use with Web Parts. I did some looking around and reflection and found no alternative for Web Controls and so I tried to use the SPUserCodeWebPart control to wrap a Web Control. To ensure you don't go down the same route, this doesn't work - it appears that you can only use classes that inherit from WebPart and anything else simply won't work.
If I do come across a way to do it, I'll be back.