Hace poco tuve que hacer algo semejante, sinceramente este es un tema que me falta dominar, no es exactamente lo que necesitas , pero tal vez te sirva de algo como ejemplo, la intencion cuando hice esto fue tener controles personalizados con una funcion en especifico, como establecer automaticamente un papel tapiz de acuerdo a la hora, otro control que accesara a datos y presentara un registro de varios usuarios, etc... la especificacion para este proyecto fue que fuera posible que la aplicacion una vez ya implementada fuera posible actualizar las librerias que contienen los controles y agregar mas, asi que utilize este codigo, el cual ya lo tengo publicado en un blog, no se que tan correcto sea hacerlo asi, ya que he leido que lo mejor es cargar los ensamblados en nuevos dominios de aplicacion, pero asi resolvi esto en su momento, espero te sirva de algo.
Para empezar cree un nuevo proyecto de libreria de clases y como medida para estandarizar los nombres de los controles y los nombres de archivo sor los mismos, esto es por que hay que especificar el nombre de la clase que esta dentro del ensamblado (dll) de la cual deseas intanciar un objeto, y pues aqui como todo es dinamico, el intellisense no ayuda.
Asi que cree mi control y posteriormente lo genere, puse esta dll en el mismo directorio de mi aplicacion principal.
Entonces en mi aplicacion principal que seria la que carga los "plug-ins" le agrege esta funcion, si no me equivoco es necesaria la referencia System.Reflection
Public Sub AddAssembly(ByVal Path As String)
'Declaro mi objeto del tipo Assembly, y cargo el fichero
'El cual es el path donde se ubica mi dll
Dim MyAssembly As Assembly = Assembly.LoadFile(Path)
'Como el nombre de mi control, mi ensamblado y mi clase son iguales
'la referencia para un control instanciado de la clase MyControl seria
'MyControl.MyControl asi que aqui simplemente extraigo el nombre de mi
'archivo sin la extension, se vera algo rudimentario pero funciona :)
Dim sClase As String = MyAssembly.ManifestModule.Name.Split(CChar("."))(0)
'Aqui obtengo la definicion del tipo de dato que tengo en mi Dll
Dim MyExtType As Type = MyAssembly.GetType(sClase & "." & sClase)
'Entonces creo la instancia nueva de acuerdo al tipo de dato obtenido
'la almaceno en mi objeto tipo object
Dim MyExtObj As Object = Activator.CreateInstance(MyExtType)
'Creo mi tabPage
Dim NewTabPage As New TabPage
'Aqui convierto mi objeto a control, probablemente esto deberia ir en
'un try catch para obtener alguna exepcion, por ejemplo que la DLL no contenga
'controles, entonces mi objeto no seria "casteable" a "control"
Dim MyControl As Control = CType(MyExtObj, Control)
'Agrego el nuevo control creado a mi TabPage
NewTabPage.Controls.Add(MyControl)
'Agrego el nuevo TabPage a mi TabControl
form.TabControl1.TabPages.Add(NewTabPage)
End Sub
Entonces con un for each obtuve cada dll de un directorio e intente convertirlo a "control" para agregar cada dll en un tab page nuevo.
El unico problema de esto es que una vez cargado un ensamblado no se puede descargar a menos de que crees un AppDomain para cargarlo ahi y despues descargar el AppDomain.
Espero esto te de un idea de como hacer tu sistema, y si algo esta mal acepto criticas.
Saludos