-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathProgram.cs
More file actions
129 lines (105 loc) · 5.01 KB
/
Copy pathProgram.cs
File metadata and controls
129 lines (105 loc) · 5.01 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
using CommandLine;
using System.Reflection;
namespace Metacrack
{
public class Program
{
private static Type[] _optionTypes;
private static Type[] _pluginTypes;
private static string[] InternalPlugins = new string[] { "catalog", "cut", "export", "lookup", "map", "parse", "rank", "sort", "split", "sql", "validate", "help", "hash" };
public static void Main(string[] args)
{
if (args.Length == 0) return;
var name = args[0].ToLower();
Assembly pluginAssembly = null;
//Determine if we are using an internal plugin
if (InternalPlugins.Contains(name))
{
pluginAssembly = Assembly.GetExecutingAssembly();
}
else
{
//Try get an assembly matching the first argument
pluginAssembly = LoadPlugin(name);
if (pluginAssembly == null) return;
}
//https://github.com/commandlineparser/commandline/wiki/Verbs
LoadTypes(pluginAssembly);
var parsed = Parser.Default.ParseArguments(args, _optionTypes);
parsed.WithParsed(Run);
parsed.WithNotParsed(HandleErrors);
}
private static void Run(object obj)
{
//Map the verb name in the option to the name in the plugin, and start the plugin
foreach (var type in _optionTypes)
{
if (obj.GetType() == type)
{
var attr = type.GetCustomAttribute<VerbAttribute>();
foreach (var type2 in _pluginTypes)
{
var name = type2.Name.Replace("Plugin", "").ToLower();
var attr2 = type2.GetCustomAttribute<PluginAttribute>();
if (attr2 != null) name = attr2.Name;
if (attr.Name == name)
{
ConsoleUtil.WriteMessage($"Using {name} plugin.", ConsoleColor.DarkYellow);
//Try regular synchronous invoke
var method = type2.GetMethod("Process", BindingFlags.Public | BindingFlags.Static);
if (method != null)
{
method.Invoke(null, new object[] { obj });
return;
}
//Try async method
method = type2.GetMethod("ProcessAsync", BindingFlags.Public | BindingFlags.Static);
if (method != null)
{
var task = (Task) method.Invoke(null, new object[] { obj });
task.GetAwaiter().GetResult();
return;
}
}
}
}
}
//Display exception message here
ConsoleUtil.WriteMessage($"Could not find plugin or options.", ConsoleColor.DarkRed);
}
private static void HandleErrors(IEnumerable<Error> obj)
{
//Display exception message here
//foreach (var error in obj) ConsoleUtil.WriteMessage($"{error}", ConsoleColor.DarkRed);
}
//load all types using Reflection
private static void LoadTypes(Assembly assembly)
{
_optionTypes = assembly.GetTypes().Where(t => t.GetCustomAttribute<VerbAttribute>() != null).ToArray();
_pluginTypes = assembly.GetTypes().Where(t => t.Name.EndsWith("Plugin")).ToArray();
}
//dll must be located in the plugins folder and match the pattern with *<name>Plugin.dll
private static Assembly LoadPlugin(string name)
{
// Navigate up to the solution root
//var pluginFolder = $"{Directory.GetCurrentDirectory()}\\Plugins\\";
var pluginFolder = $"{AppDomain.CurrentDomain.BaseDirectory}\\Plugins\\{name}\\";
if (!Directory.Exists(pluginFolder))
{
ConsoleUtil.WriteMessage($"Could not find a plugin folder for {name}.", ConsoleColor.DarkRed);
ConsoleUtil.WriteMessage($"{pluginFolder}", ConsoleColor.DarkRed);
return null;
}
var files = Directory.GetFiles(pluginFolder, $"*Plugin.dll");
if (files.Length == 0)
{
ConsoleUtil.WriteMessage($"Could not find a plugin dll matching {name}.", ConsoleColor.DarkRed);
ConsoleUtil.WriteMessage($"Expected to find plugin *Plugin.dll in {pluginFolder}.", ConsoleColor.DarkRed);
return null;
}
var pluginLocation = files[0];
var loadContext = new PluginLoadContext(pluginLocation);
return loadContext.LoadFromAssemblyName(new AssemblyName(Path.GetFileNameWithoutExtension(pluginLocation)));
}
}
}