diff --git a/MBS.Framework/Application.cs b/MBS.Framework/Application.cs index a1b160e..1b6caca 100755 --- a/MBS.Framework/Application.cs +++ b/MBS.Framework/Application.cs @@ -364,12 +364,25 @@ namespace MBS.Framework Initialized = true; } + public event ApplicationActivatedEventHandler BeforeActivated; + protected virtual void OnBeforeActivated(ApplicationActivatedEventArgs e) + { + BeforeActivated?.Invoke(this, e); + } + public event ApplicationActivatedEventHandler Activated; protected virtual void OnActivated(ApplicationActivatedEventArgs e) { Activated?.Invoke(this, e); } + + public event ApplicationActivatedEventHandler AfterActivated; + protected virtual void OnAfterActivated(ApplicationActivatedEventArgs e) + { + AfterActivated?.Invoke(this, e); + } + protected virtual int StartInternal() { CommandLine cline = new CommandLine(); @@ -413,14 +426,61 @@ namespace MBS.Framework } ApplicationActivatedEventArgs e = new ApplicationActivatedEventArgs(true, ApplicationActivationType.CommandLineLaunch, cline); + + if (CommandLine.Options["help"]?.Value is bool && ((bool)CommandLine.Options["help"]?.Value) == true) + { + if (ShowCommandLineHelp(out int resultCode)) + { + return resultCode; + } + } + if (cline.Command != null && cline.Command.ActivationDelegate != null) { + OnBeforeActivated(e); + if (!e.Success) + { + Console.WriteLine(String.Format("Try '{0} --help' for more information.", ShortName)); + return e.ExitCode; + } + // use the activation delegate instead of calling OnActivated cline.Command.ActivationDelegate(e); + if (!e.Success) + { + Console.WriteLine(String.Format("Try '{0} --help' for more information.", ShortName)); + return e.ExitCode; + } + + OnAfterActivated(e); + if (!e.Success) + { + Console.WriteLine(String.Format("Try '{0} --help' for more information.", ShortName)); + return e.ExitCode; + } } else { + OnBeforeActivated(e); + if (!e.Success) + { + Console.WriteLine(String.Format("Try '{0} --help' for more information.", ShortName)); + return e.ExitCode; + } + OnActivated(e); + if (!e.Success) + { + Console.WriteLine(String.Format("Try '{0} --help' for more information.", ShortName)); + return e.ExitCode; + } + + OnAfterActivated(e); + if (!e.Success) + { + Console.WriteLine(String.Format("Try '{0} --help' for more information.", ShortName)); + return e.ExitCode; + } } return e.ExitCode; } @@ -428,12 +488,32 @@ namespace MBS.Framework protected void PrintUsageStatement(CommandLineCommand command = null) { + string shortOptionPrefix = CommandLine.ShortOptionPrefix ?? "-"; + string longOptionPrefix = CommandLine.LongOptionPrefix ?? "--"; + Console.Write("usage: {0} ", ShortName); foreach (CommandLineOption option in CommandLine.Options) { PrintUsageStatementOption(option); } + + if (CommandLine.HelpTextPrefix != null) + { + Console.WriteLine(); + Console.WriteLine(); + Console.WriteLine(CommandLine.HelpTextPrefix); + } + Console.WriteLine(); + + bool printDescriptions = true; + if (printDescriptions) + { + foreach (CommandLineOption option in CommandLine.Options) + { + Console.WriteLine(" {0}{1}", option.Abbreviation != '\0' ? String.Format("{0}{1}, {2}{3}", shortOptionPrefix, option.Abbreviation, longOptionPrefix, option.Name) : String.Format("{0}{1}", longOptionPrefix, option.Name), option.Description == null ? null : String.Format(" - {0}", option.Description)); + } + } // Console.Write("[]"); if (command != null) @@ -462,6 +542,12 @@ namespace MBS.Framework } } } + + if (CommandLine.HelpTextSuffix != null) + { + Console.WriteLine(); + Console.WriteLine(CommandLine.HelpTextSuffix); + } } private void PrintUsageStatementOption(CommandLineOption option) @@ -543,6 +629,10 @@ namespace MBS.Framework index++; option.Value = args[index]; } + else + { + option.Value = true; + } if (list != null) list.Add(option); @@ -573,6 +663,10 @@ namespace MBS.Framework // option.Value = args[index]; option.Value = value; } + else + { + option.Value = true; + } list.Add(option); } else @@ -832,5 +926,13 @@ namespace MBS.Framework { _settings[id] = value; } + + protected virtual bool ShowCommandLineHelp(out int resultCode) + { + // bash: cd returns 2 if --help is specified OR invalid option selected, 1 if file not found + PrintUsageStatement(); + resultCode = 2; + return true; + } } } diff --git a/MBS.Framework/ApplicationActivatedEvent.cs b/MBS.Framework/ApplicationActivatedEvent.cs index 8dbfa1e..0a27f40 100755 --- a/MBS.Framework/ApplicationActivatedEvent.cs +++ b/MBS.Framework/ApplicationActivatedEvent.cs @@ -25,6 +25,8 @@ namespace MBS.Framework { public class ApplicationActivatedEventArgs : EventArgs { + public bool Success { get; set; } = true; + public bool FirstRun { get; } = true; public CommandLine CommandLine { get; } = null; public int ExitCode { get; set; } = 0; diff --git a/MBS.Framework/ArrayExtensions.cs b/MBS.Framework/ArrayExtensions.cs old mode 100755 new mode 100644 index 1ffcbfa..37775c4 --- a/MBS.Framework/ArrayExtensions.cs +++ b/MBS.Framework/ArrayExtensions.cs @@ -93,5 +93,13 @@ namespace MBS.Framework } return true; } + + public static T[] Concat(T[] array1, T[] array2) + { + T[] array3 = new T[array1.Length + array2.Length]; + Array.Copy(array1, 0, array3, 0, array1.Length); + Array.Copy(array2, 0, array3, array1.Length, array2.Length); + return array3; + } } } diff --git a/MBS.Framework/Collections/ExtensionMethods.cs b/MBS.Framework/Collections/ExtensionMethods.cs index fb63319..48b6f33 100755 --- a/MBS.Framework/Collections/ExtensionMethods.cs +++ b/MBS.Framework/Collections/ExtensionMethods.cs @@ -26,6 +26,33 @@ namespace MBS.Framework.Collections { public static class ExtensionMethods { + public static bool ContainsAny(this IEnumerable enumerable, T[] item) + { + foreach (object item1 in enumerable) + { + foreach (T item2 in item) + { + if (item1 is T) + { + if (item1.Equals(item2)) + return true; + } + } + } + return false; + } + public static bool ContainsAny(this System.Collections.Generic.IEnumerable enumerable, T[] item) + { + foreach (T item1 in enumerable) + { + foreach (T item2 in item) + { + if (item1.Equals(item2)) + return true; + } + } + return false; + } public static T[] ToArray(this IEnumerable enumerable) where T : class { System.Collections.Generic.List list = new System.Collections.Generic.List(); diff --git a/MBS.Framework/Collections/Generic/HandleDictionary.cs b/MBS.Framework/Collections/Generic/HandleDictionary.cs index 25c8fa5..03489d6 100755 --- a/MBS.Framework/Collections/Generic/HandleDictionary.cs +++ b/MBS.Framework/Collections/Generic/HandleDictionary.cs @@ -43,6 +43,15 @@ namespace MBS.Framework.Collections.Generic _dict.Add(handle, obj); } + public bool ContainsObject(TObject obj) + { + return _dict.ContainsValue2(obj); + } + public bool ContainsHandle(THandle handle) + { + return _dict.ContainsValue1(handle); + } + public bool Contains(TObject obj) { return _dict.ContainsValue2(obj); diff --git a/MBS.Framework/CommandLine.cs b/MBS.Framework/CommandLine.cs index 1705c68..3df0825 100755 --- a/MBS.Framework/CommandLine.cs +++ b/MBS.Framework/CommandLine.cs @@ -39,6 +39,9 @@ namespace MBS.Framework public CommandLineParser Parser { get; set; } = null; + public string HelpTextPrefix { get; set; } = null; + public string HelpTextSuffix { get; set; } = null; + public CommandLineOption.CommandLineOptionCollection Options { get; } = new CommandLineOption.CommandLineOptionCollection(); public CommandLineCommand.CommandLineCommandCollection Commands { get; } = new CommandLineCommand.CommandLineCommandCollection(); public CommandLineCommand Command { get; internal set; } = null; diff --git a/MBS.Framework/CommandLineOptionValueType.cs b/MBS.Framework/CommandLineOptionValueType.cs index ae6afc9..86f9936 100755 --- a/MBS.Framework/CommandLineOptionValueType.cs +++ b/MBS.Framework/CommandLineOptionValueType.cs @@ -23,8 +23,17 @@ namespace MBS.Framework { public enum CommandLineOptionValueType { + /// + /// The option accepts no values. + /// None = 0, + /// + /// The option accepts a single value. + /// Single = 1, + /// + /// The option accepts multiple values. + /// Multiple = 2 } } diff --git a/MBS.Framework/NanoId.cs b/MBS.Framework/NanoId.cs index 4738a7c..d5c8d98 100755 --- a/MBS.Framework/NanoId.cs +++ b/MBS.Framework/NanoId.cs @@ -161,7 +161,9 @@ namespace MBS.Framework } - private const string DefaultAlphabet = "_-0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + public const string DefaultAlphabet = "_-0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + public const string DefaultAlphabetNoSpecialChars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + private static readonly CryptoRandom Random = new CryptoRandom(); /// /// diff --git a/MBS.Framework/Reflection.cs b/MBS.Framework/Reflection.cs index d1df0bc..0e099a3 100755 --- a/MBS.Framework/Reflection.cs +++ b/MBS.Framework/Reflection.cs @@ -97,6 +97,7 @@ namespace MBS.Framework } + private static object available_assemblies_lock = new object(); private static Assembly[] mvarAvailableAssemblies = null; /// /// Gets the available assemblies in the given search paths, or the current application directory if no search paths are specified. @@ -105,7 +106,7 @@ namespace MBS.Framework /// An array of paths to search in. public static Assembly[] GetAvailableAssemblies(string[] searchPaths = null) { - if (mvarAvailableAssemblies == null) + if (mvarAvailableAssemblies == null || searchPaths != null) { List list = new List(); @@ -139,27 +140,40 @@ namespace MBS.Framework Assembly asm = Assembly.LoadFile(FileName); list.Add(asm); } - catch + catch (Exception ex) { } } } - mvarAvailableAssemblies = list.ToArray(); + if (searchPaths == null) + { + mvarAvailableAssemblies = list.ToArray(); + } + else + { + return list.ToArray(); + } } return mvarAvailableAssemblies; } private static Type[] mvarAvailableTypes = null; - public static Type[] GetAvailableTypes(Type[] inheritsFrom = null) + public static Type[] GetAvailableTypes(Type[] inheritsFrom = null, Assembly[] additionalAssemblies = null) { if (mvarAvailableTypes == null) { List types = new List(); Assembly[] asms = GetAvailableAssemblies(); - for (int iAsm = 0; iAsm < asms.Length; iAsm++) + List listAsms = new List(asms); + if (additionalAssemblies != null) { - Assembly asm = asms[iAsm]; + listAsms.AddRange(additionalAssemblies); + } + + for (int iAsm = 0; iAsm < listAsms.Count; iAsm++) + { + Assembly asm = listAsms[iAsm]; Type[] types1 = null; try {