public void LoadModule(CliModuleBase module) { var cliModuleAttribute = module.GetType().GetCustomAttribute <CliModuleAttribute>(); CliConsole.WriteLine($"module ({cliModuleAttribute.ModuleName})"); ModuleNames.Add(cliModuleAttribute.ModuleName); MethodsByModules[cliModuleAttribute.ModuleName] = new List <string>(); var methods = module.GetType().GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly); foreach (MethodInfo methodInfo in methods.OrderBy(m => m.Name)) { var cliProperty = methodInfo.GetCustomAttribute <CliPropertyAttribute>(); var cliFunction = methodInfo.GetCustomAttribute <CliFunctionAttribute>(); bool isProperty = cliProperty != null; string objectName = cliProperty?.ObjectName ?? cliFunction?.ObjectName; string itemName = cliProperty?.PropertyName ?? cliFunction?.FunctionName; if (objectName == null) { throw new InvalidDataException($"Method {methodInfo.Name} of {module.GetType().Name} should be decorated with one of {nameof(CliPropertyAttribute)} or {nameof(CliFunctionAttribute)}"); } ObjectInstance instance; if (!_objects.ContainsKey(objectName)) { instance = _engine.JintEngine.Object.Construct(Arguments.Empty); _engine.JintEngine.SetValue(objectName, instance); _objects[objectName] = instance; } instance = _objects[objectName]; var @delegate = CreateDelegate(methodInfo, module); DelegateWrapper nativeDelegate = new DelegateWrapper(_engine.JintEngine, @delegate); if (isProperty) { CliConsole.WriteKeyword($" {objectName}"); CliConsole.WriteLine($".{itemName}"); MethodsByModules[objectName].Add(itemName); AddProperty(instance, itemName, nativeDelegate); } else { CliConsole.WriteKeyword($" {objectName}"); CliConsole.WriteLine($".{itemName}({string.Join(", ", methodInfo.GetParameters().Select(p => p.Name))})"); MethodsByModules[objectName].Add(itemName + "("); AddMethod(instance, itemName, nativeDelegate); } } CliConsole.WriteLine(); }