-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
c455c77
commit 4ccd890
Showing
23 changed files
with
278 additions
and
261 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,11 @@ | ||
namespace BitzArt.Console; | ||
|
||
[AppMenu("Main Menu", IsMain = true)] | ||
internal class MainMenu : ConsoleSelectionMenu | ||
{ | ||
public override string Title => "Main Menu"; | ||
protected override bool IsMainMenu => true; | ||
|
||
public MainMenu() | ||
[MenuSelectionItem("Veggies")] | ||
public async Task SubmenuVeggiesAsync() | ||
{ | ||
AddSubmenu<FruitsMenu>("1. Fruits"); | ||
AddSubmenu<VeggiesMenu>("2. Veggies"); | ||
await RunAsync<VeggiesMenu>(); | ||
} | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
using System.Reflection; | ||
|
||
namespace BitzArt.Console; | ||
|
||
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] | ||
public class AppMenuAttribute : Attribute | ||
{ | ||
private readonly string _title = "Menu"; | ||
|
||
public bool IsMain { get; set; } = false; | ||
|
||
public AppMenuAttribute(string title) | ||
{ | ||
if (string.IsNullOrWhiteSpace(title)) | ||
{ | ||
throw new ArgumentException("Menu title cannot be empty.", nameof(title)); | ||
} | ||
|
||
_title = title; | ||
} | ||
|
||
internal string GetTitle() => _title; | ||
} | ||
|
||
internal static class AppMenuAttributeExtensions | ||
{ | ||
public static AppMenuAttribute GetAppMenuAttribute(this Type type) | ||
{ | ||
var attribute = type.GetCustomAttribute<AppMenuAttribute>() | ||
?? throw new InvalidOperationException($"Menu {type.Name} must have {nameof(AppMenuAttribute)}"); | ||
|
||
return attribute; | ||
} | ||
} |
50 changes: 50 additions & 0 deletions
50
src/BitzArt.Console/Attributes/MenuSelectionItemAttribute.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
using System.Reflection; | ||
|
||
namespace BitzArt.Console; | ||
|
||
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] | ||
public class MenuSelectionItemAttribute : Attribute | ||
{ | ||
private readonly string _name; | ||
public bool PauseOnComplete { get; set; } = false; | ||
|
||
public MenuSelectionItemAttribute(string name) | ||
{ | ||
if (string.IsNullOrWhiteSpace(name)) | ||
{ | ||
throw new ArgumentException("Selection item name cannot be empty.", nameof(name)); | ||
} | ||
|
||
_name = name; | ||
} | ||
|
||
internal string GetName() => _name; | ||
} | ||
|
||
internal static class MenuSelectionItemAttributeExtensions | ||
{ | ||
internal static IEnumerable<SelectionMethod> GetSelectionMethods(this Type type) | ||
{ | ||
var allPublicMethods = type.GetMethods(); | ||
|
||
var result = new List<SelectionMethod>(); | ||
|
||
foreach (var method in allPublicMethods) | ||
{ | ||
var attribute = method.GetCustomAttribute<MenuSelectionItemAttribute>(); | ||
if (attribute is null) continue; | ||
|
||
result.Add(new SelectionMethod(attribute.GetName(), method, attribute.PauseOnComplete)); | ||
} | ||
|
||
return result; | ||
} | ||
|
||
internal static MenuSelectionItemAttribute GetMenuSelectionItemAttribute(this MethodInfo method) | ||
{ | ||
var attribute = method.GetCustomAttribute<MenuSelectionItemAttribute>() | ||
?? throw new InvalidOperationException($"Method {method.Name} must have {nameof(MenuSelectionItemAttribute)}"); | ||
|
||
return attribute; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
40 changes: 29 additions & 11 deletions
40
src/BitzArt.Console/Extensions/RunConsoleMenuExtension.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,35 +1,53 @@ | ||
using Microsoft.Extensions.DependencyInjection; | ||
using System; | ||
|
||
namespace BitzArt.Console; | ||
|
||
public static class RunConsoleMenuExtension | ||
{ | ||
internal static async Task RunConsoleMenuAsync<TConsoleMenu>(this IServiceProvider serviceProvider) | ||
where TConsoleMenu : IConsoleMenu | ||
where TConsoleMenu : class | ||
{ | ||
var menu = serviceProvider.GetRequiredService<TConsoleMenu>(); | ||
|
||
AttachApp(menu, serviceProvider); | ||
if (menu is not ConsoleMenu consoleMenu) return; | ||
|
||
consoleMenu.Populate(serviceProvider); | ||
|
||
await menu.RunAsync(); | ||
await consoleMenu.RunAsync(); | ||
} | ||
|
||
internal static async Task RunConsoleMenuAsync(this IServiceProvider serviceProvider, Type menuType) | ||
{ | ||
if (!menuType.IsAssignableTo(typeof(IConsoleMenu))) throw new ArgumentException($"Menu Type must implement {nameof(IConsoleMenu)}", nameof(menuType)); | ||
var menu = serviceProvider.GetRequiredService(menuType); | ||
|
||
var menu = (IConsoleMenu)serviceProvider.GetRequiredService(menuType); | ||
if (menu is not ConsoleMenu consoleMenu) return; | ||
|
||
AttachApp(menu, serviceProvider); | ||
consoleMenu.Populate(serviceProvider); | ||
|
||
await menu.RunAsync(); | ||
await consoleMenu.RunAsync(); | ||
} | ||
|
||
private static void AttachApp(this IConsoleMenu menu, IServiceProvider serviceProvider) | ||
private static void Populate(this ConsoleMenu menu, IServiceProvider serviceProvider) | ||
{ | ||
if (menu is not ConsoleMenu consoleMenu) return; | ||
|
||
var app = serviceProvider.GetService<ConsoleApp>(); | ||
consoleMenu.App = app; | ||
menu.App = app; | ||
|
||
var appMenuAttribute = menu.GetType().GetAppMenuAttribute(); | ||
menu.Title = appMenuAttribute!.GetTitle(); | ||
menu.IsMainMenu = appMenuAttribute.IsMain; | ||
|
||
menu.PopulateSelectionFromMethods(); | ||
} | ||
|
||
private static void PopulateSelectionFromMethods(this ConsoleMenu consoleMenu) | ||
{ | ||
if (consoleMenu is not ConsoleSelectionMenu selectionMenu) return; | ||
|
||
var selections = consoleMenu.GetType().GetSelectionMethods(); | ||
foreach (var selection in selections) | ||
{ | ||
selectionMenu.AddSelection(selection.Name, () => selection.Method.Invoke(selectionMenu, null), selection.PauseOnComplete); | ||
} | ||
} | ||
} |
Oops, something went wrong.