All Projects → wwh1004 → ToolLoader

wwh1004 / ToolLoader

Licence: other
A loader for the tools which depend on given framework version and platform

Programming Languages

C#
18002 projects

ToolLoader

A loader for the tools which depends on given framework version and platform

Usages

Code

Apply OptionAttribute to property

Attribute

OptionAttribute.cs:

/// <summary>
/// Represents a command line option. The property which <see cref="OptionAttribute"/> is applied to must be an instance property and one of the following types: <see cref="bool"/>, <see cref="char"/>, <see cref="sbyte"/>, <see cref="byte"/>, <see cref="short"/>, <see cref="ushort"/>, <see cref="int"/>, <see cref="uint"/>, <see cref="long"/>, <see cref="ulong"/>, <see cref="float"/>, <see cref="double"/>, <see cref="decimal"/>, <see cref="DateTime"/>, <see cref="string"/>, <see cref="Enum"/> or array of them.
/// </summary>
[AttributeUsage(AttributeTargets.Property)]
public sealed class OptionAttribute : Attribute {
	/// <summary>
	/// Option name
	/// </summary>
	public string Name { get; }

	/// <summary>
	/// Whether it is a default option
	/// </summary>
	public bool IsDefault => string.IsNullOrEmpty(Name);

	/// <summary>
	/// Whether it is a required option
	/// </summary>
	public bool IsRequired { get; set; }

	/// <summary>
	/// Array separator, which is used to split value when option type is array
	/// </summary>
	public char Separator { get; set; } = ',';

	/// <summary>
	/// By default, when <see cref="IsRequired"/> is <see langword="true"/>, <see cref="DefaultValue"/> must be <see langword="null"/>
	/// </summary>
	public object? DefaultValue { get; set; }

	/// <summary>
	/// Option description, which is used to describe this option
	/// </summary>
	public string Description { get; set; } = string.Empty;

	/// <summary>
	/// Constructor
	/// </summary>
	public OptionAttribute() {
		Name = string.Empty;
	}

	/// <summary>
	/// Constructor
	/// </summary>
	/// <param name="name">Option name</param>
	public OptionAttribute(string name) {
		Name = name;
	}
}

ChildOptionsAttribute.cs:

/// <summary>
/// Marks current type as child of <see cref="Parent"/>. <see cref="Parent"/> type must have instance property 'ChildOptions' with return type 'IDictionary&lt;Type, object&gt;'
/// </summary>
[AttributeUsage(AttributeTargets.Class)]
public sealed class ChildOptionsAttribute : Attribute {
	/// <summary>
	/// Parent options type
	/// </summary>
	public Type Parent { get; }

	/// <summary>
	/// Option prefix (can be empty)
	/// </summary>
	public string Prefix { get; set; } = string.Empty;

	/// <summary>
	/// Constructor
	/// </summary>
	/// <param name="parent">Parent options type</param>
	/// <exception cref="ArgumentNullException"></exception>
	public ChildOptionsAttribute(Type parent) {
		Parent = parent ?? throw new ArgumentNullException(nameof(parent));
	}
}

Example:

enum ToolEnum {
	EnumA,
	EnumB
}

sealed class ToolOptions {
	public IDictionary<Type, object> ChildOptions { get; } = new Dictionary<Type, object>();

	[Option(Description = "A string value, this is default option")]
	public string DefaultOption { get; set; }

	[Option("-r", IsRequired = true, Description = "A string value")]
	public string RequiredOption { get; set; }

	[Option("-o", DefaultValue = ToolEnum.EnumB, Description = "An enum value")]
	public ToolEnum OptionalOption { get; set; }

	[Option("-o2", DefaultValue = new ToolEnum[] { ToolEnum.EnumA, ToolEnum.EnumB }, Description = "Some enum values")]
	public ToolEnum[] OptionalOption2 { get; set; }

	public T ChildOption<T>() {
		return (T)ChildOptions[typeof(T)];
	}
}

[ChildOptions(typeof(ToolOptions))]
sealed class ChildToolOptions1 {
	[Option("-child1-o1", Description = "A child option", DefaultValue = "My default value")]
	public string ChildOption1 { get; set; }
}

[ChildOptions(typeof(ToolOptions), Prefix = "-child2")]
sealed class ChildToolOptions2 {
	[Option("-o2", Description = "Another child option")]
	public string ChildOption2 { get; set; }
}

sealed class Tool : ITool<ToolOptions> {
	public string Title => null;

	public void Execute(ToolOptions options) {
		Logger.Level = LogLevel.Verbose1;
		Logger.Info($"LogLevel: {Logger.Level}");
		Logger.Info("Info");
		Logger.Warning("Warning");
		Logger.Error("Error");
		Logger.Verbose1($"Verbose1, options.ChildOptions.Count: {options.ChildOptions.Count:X8}");
		Logger.Verbose2("Verbose2");
		Logger.Verbose3("Verbose3");
		Logger.Verbose3($"Verbose{3:X} with InterpolatedStringHandler: {typeof(Logger.Verbose3InterpolatedStringHandler)}");

		var separator = new string('*', options.RequiredOption.Length);
		Logger.Info(separator);
		Logger.Info($"DefaultOption: {options.DefaultOption}");
		Logger.Info($"RequiredOption: {options.RequiredOption}");
		Logger.Info($"OptionalOption: {options.OptionalOption}");
		Logger.Info($"OptionalOption2: {string.Join(", ", options.OptionalOption2)}");
		Logger.Info($"ChildOption1: {options.ChildOption<ChildToolOptions1>().ChildOption1}");
		Logger.Info($"ChildOption2: {options.ChildOption<ChildToolOptions2>().ChildOption2}");
		Logger.Info(separator);

		var lockedLogger = Logger.EnterLock();
		lockedLogger.Info($"Lock mode | IsLocked: {lockedLogger.IsLocked}");
		new Thread(() => Logger.Warning($"I'm blocked | IsLocked: {lockedLogger.IsLocked}")).Start();
		Thread.Sleep(2000);
		lockedLogger.ExitLock();
		Logger.Info($"No lock mode | IsLocked: {lockedLogger.IsLocked}");

		Logger.Info("Exception test");
		try {
			throw new ApplicationException("test");
		}
		catch (Exception ex) {
			Logger.Exception(ex);
		}

		Logger.Flush();
	}
}

CLI

Syntax:

Command:

Tool.Loader.*.exe <tool-name.dll> <arguments>

Show usage:

Tool.Loader.*.exe <tool-name.dll> -h

Example:

Command:

Tool.Loader.CLR40.x64.exe TestTool.dll -r TestTool.dll1 Test2 -o EnumA -o2 EnumA,EnumA,EnumB -child2-o2 test

Output:

LogLevel: Verbose1
Info
Warning
Error
Verbose1, options.ChildOptions.Count: 00000002
*************
DefaultOption: Test2
RequiredOption: TestTool.dll1
OptionalOption: EnumA
OptionalOption2: EnumA, EnumA, EnumB
ChildOption1: My default value
ChildOption2: test
*************
Lock mode | IsLocked: True
I'm blocked | IsLocked: True
No lock mode | IsLocked: False
Exception test
Type:
System.ApplicationException
Message:
test
Source:
TestTool
StackTrace:
   at TestTool.Tool.Execute(ToolOptions options) in D:\Projects\ToolLoader\TestTool\Tool.cs:line 41
TargetSite:
Void Execute(TestTool.ToolOptions)
----------------------------------------

Press any key to exit...

Show usage:

Tool.Loader.CLR40.x64.exe TestTool.dll -h

Output:

Use -h --h /h -help --help /help to show these usage tips.
Options:
  <default>   String      A string value, this is default option  (Optional)
  -r          String      A string value
  -o          ToolEnum    An enum value                           (Optional)
  -o2         ToolEnum[]  Some enum values                        (Optional)
  -child1-o1  String      A child option                          (Optional)
  -child2-o2  String      Another child option                    (Optional)

Press any key to exit...

Downloads

GitHub: Latest release

AppVeyor: Build status

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].