Building a SmartPart type control really isn't all that complicated. On a project I did in the past, I came into a situation where I couldn't use the SmartPart. I needed specific functionality and unforutnately at the time, the source code for the SmartPart was not available. Therefore, I decided to see if I can build my own. In its simplest form, all you are really doing is calling Page.LoadControl and passing it a path to your user control. Of course it's a little more complicated than that but not really. Let's start by looking at the beginning of the web part.
[SupportsAttributeMarkup(true), XmlRoot(Namespace = "http://schemas.mydomain.com/WebPart/MySmartPart")]
public class MySmartPart : Microsoft.SharePoint.WebPartPages.WebPart
// this provides a refernece to the control we are loading
private Control myControl;
[Personalizable(PersonalizationScope.Shared), WebBrowsable(true), WebDisplayName("Control Path"), WebDescription("Specify a path to a user control.")]
[WebPartStorage(Storage.Shared), Browsable(false), DefaultValue("")]
public string ControlPath
So far what we have is a new class inheriting from WebPart which has a member variable to reference the control itself as well as a property to contain the path to the control. The ControlPath has attributes on it so that it can be set via CAML or through the UI in SharePoint. When the user specifies a path it can be on any relative URL on the site (not just in a UserControls folder). The next part is to actually load the control and add it to the web part.
protected override void CreateChildControls()
// don't use LoadControl if you already have a reference to the control
if (myControl == null)
myControl = Page.LoadControl(ControlPath);
We start by overriding CreateChildControls and calling the base method. Then, we check to see if the control already exists or not. This is so that you don't load a new instance of the control on postbacks. Then, we just call Page.LoadControl and add it to the Controls collection. This is really all that is required to get up and running with a web part that displays a user control. One thing that is different is that typically in ASP.NET when you load a control with Page.LoadControl, you need to specify an Id on the control for postbacks to work properly. However, you don't want to do this in your web part. For whatever reason, it will lead to very inconsistent behavior with your postbacks. There isn't any error checking or anything in the above example, so you might want to check to make sure that the path is valid, that the control was able to load, and look for exceptions.
Also, this web part pretty much has to run with full trust. That means you'll have to put it in the GAC or run SharePoint with full trust. I hate running thing with full trust, but I discovered something pretty deep in the call stack of Page.LoadControl that requires full trust. It's pretty simple, but maybe it will be of use to you if you ever need to do something more advanced when loading a user control (i.e.: passing parameters).