VB.NET•Build Menus at Run Time

Listing 1. Building menus at run time allows you to combine standard menu options with ones that derive directly from available assemblies. You can identify appropriate types by their base class or by attributes, and you can use other attributes to specify captions and the location of new options.

Protected Overridable Sub BuildMenuFromAssembly()
	Dim assemblies As Reflection.Assembly()
	Dim types As System.Type()
	Dim baseMenu As Windows.Forms.Menu
	Dim deleg As System.Delegate
	Dim mnu As Windows.Forms.MenuItem
	If mnuMain Is Nothing Then
		Throw New _
			System.ApplicationException( _
			"Internal error - mnuMain is nothing")
		assemblies = Me.GetAssemblies
		For Each assem As Reflection.Assembly In _
			If Array.IndexOf(ignoreAssemblies, _
				assem.GetName.Name) < 0 AndAlso _
				Not assem.GetName.Name.StartsWith( _
				"System") Then
				types = assem.GetTypes
				For Each type As System.Type In _
					If IsValidChildForm(type) Then
						baseMenu = _
						mnu = New MenuItemWithType( _
							Me.GetCaption(type), _
							AddressOf _
							mnuDynamicItem_Click, _
							baseMenu.MenuItems.Add _
					End If
			End If
	End If
End Sub

Protected Overridable Function GetAssemblies() _
	As Reflection.Assembly()
	Return Threading.Thread.CurrentThread. _
End Function

Private Function IsValidChildForm(ByVal type As _
	System.Type) As Boolean
	Dim ret As Boolean
	If Utility.GetCustomTypeAttribute( _
		type, "DynamicSupport.ExcludeFromMenus" &_
		"Attribute") Is Nothing Then
		If type.IsSubclassOf(GetType( _
			DynamicSupport.BaseEditForm)) Then
			Return True
		ElseIf Not type.GetInterface( _
			"DynamicSupport.IProcess") Is Nothing _
			Return True
		ElseIf Not _
			Utility.GetCustomTypeAttribute( _
			type, "DynamicSupport." &_
			"IncludeInMenuAttribute") Is Nothing _
			Return True
		End If
	End If
End Function

Protected Function GetBaseMenu(ByVal type As _
	System.Type) As Windows.Forms.Menu
	Dim obj As Object
	Dim caption As String
	Dim rescaption As String
	obj = Utility.GetCustomTypeAttribute(type, _
	If TypeOf obj Is BaseMenuAttribute Then
		caption = CType(obj, _
		rescaption = _
		If (Not rescaption Is Nothing) AndAlso _
			(rescaption.Trim.Length > 0) Then
			caption = rescaption
		End If
		Return GetBaseMenu(caption)
		Return GetDefaultMenu()
	End If
End Function

Protected Overridable Function GetDefaultMenu() _
	As Windows.Forms.MenuItem
	Return GetBaseMenu("Action")
End Function

Private Function GetBaseMenu(ByVal caption As _
	String) As Windows.Forms.MenuItem
	For Each MenuItem As Windows.Forms.MenuItem _
		In Me.mnuMain.MenuItems
		If MenuItem.Text = caption Then
			Return MenuItem
		End If
	' If we get here, it doesn't exist yet
	Return Me.mnuMain.MenuItems.Add(caption)
End Function