Esempio n. 1
0
    public static ModuleSet FromEnumerable(IEnumerable <Module> source)
    {
        var result = new ModuleSet();

        foreach (var module in source)
        {
            result.Add(module);
        }
        return(result);
    }
Esempio n. 2
0
        public int RegisterCommandClass(
            CommandEvaluationContext context,
            Type type,
            bool registerAsModule
            )
        {
            if (type.GetInterface(typeof(ICommandsDeclaringType).FullName) == null)
            {
                throw new Exception($"the type '{type.FullName}' must implements interface '{typeof(ICommandsDeclaringType).FullName}' to be registered as a command class");
            }

            var dtNamespaceAttr = type.GetCustomAttribute <CommandsNamespaceAttribute>();
            var dtNamespace     = (dtNamespaceAttr == null) ? "" : CheckAndNormalizeCommandNamespace(dtNamespaceAttr.Segments);

            var    comsCount = 0;
            object instance  = Activator.CreateInstance(type, new object[] { });
            var    methods   = type.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);

            if (registerAsModule && _modules.ContainsKey(type.FullName))
            {
                context.Errorln($"a module with same name than the commands declaring type '{type.FullName}' is already registered");
                return(0);
            }

            foreach (var method in methods)
            {
                var cmd = method.GetCustomAttribute <CommandAttribute>();
                if (cmd != null)
                {
                    if (!method.ReturnType.HasInterface(typeof(ICommandResult)))
                    {
                        context.Errorln($"class={type.FullName} method={method.Name} wrong return type. should be of type '{typeof(ICommandResult).FullName}', but is of type: {method.ReturnType.FullName}");
                    }
                    else
                    {
                        // ⏺ build the command specification from the method meta-data

                        var cmdNamespaceAttr  = method.GetCustomAttribute <CommandNamespaceAttribute>();
                        var cmdNamespace      = cmdNamespaceAttr == null ? dtNamespace : CheckAndNormalizeCommandNamespace(cmdNamespaceAttr.Segments);
                        var cmdAliasesAttrLst = method.GetCustomAttributes <CommandAliasAttribute>();
                        var cmdAliases        = cmdAliasesAttrLst?.Select(x => (x.AliasName, x.AliasText)).ToList();
                        if (cmdAliases.Count == 0)
                        {
                            cmdAliases = null;                        // convention
                        }
                        #region init from method parameters attributes

                        var  paramspecs  = new List <CommandParameterSpecification>();
                        bool syntaxError = false;
                        var  pindex      = 0;
                        foreach (var parameter in method.GetParameters())
                        {
                            if (pindex == 0)
                            {
                                // manadatory: param 0 is CommandEvaluationContext
                                if (parameter.ParameterType != typeof(CommandEvaluationContext))
                                {
                                    context.Errorln($"class={type.FullName} method={method.Name} parameter 0 ('{parameter.Name}') should be of type '{typeof(CommandEvaluationContext).FullName}', but is of type: {parameter.ParameterType.FullName}");
                                    syntaxError = true;
                                    break;
                                }
                            }
                            else
                            {
                                CommandParameterSpecification pspec = null;
                                object defval = null;
                                if (!parameter.HasDefaultValue && parameter.ParameterType.IsValueType)
                                {
                                    defval = Activator.CreateInstance(parameter.ParameterType);
                                }

                                // param
                                var paramAttr = parameter.GetCustomAttribute <ParameterAttribute>();
                                if (paramAttr != null)
                                {
                                    // TODO: validate command specification (eg. indexs validity)
                                    pspec = new CommandParameterSpecification(
                                        parameter.Name,
                                        paramAttr.Description,
                                        paramAttr.IsOptional,
                                        paramAttr.Index,
                                        null,
                                        null,
                                        true,
                                        parameter.HasDefaultValue,
                                        paramAttr.HasDefaultValue ?
                                        paramAttr.DefaultValue
                                            : ((parameter.HasDefaultValue) ? parameter.DefaultValue : defval),
                                        parameter);
                                }

                                // option
                                var optAttr = parameter.GetCustomAttribute <OptionAttribute>();
                                if (optAttr != null)
                                {
                                    var reqParamAttr = parameter.GetCustomAttribute <OptionRequireParameterAttribute>();
                                    try
                                    {
                                        pspec = new CommandParameterSpecification(
                                            parameter.Name,
                                            optAttr.Description,
                                            optAttr.IsOptional,
                                            -1,
                                            optAttr.OptionName /*?? parameter.Name*/,
                                            optAttr.OptionLongName,
                                            optAttr.HasValue,
                                            parameter.HasDefaultValue,
                                            optAttr.HasDefaultValue ?
                                            optAttr.DefaultValue
                                                : ((parameter.HasDefaultValue) ? parameter.DefaultValue : defval),
                                            parameter,
                                            reqParamAttr?.RequiredParameterName);
                                    }
                                    catch (Exception ex)
                                    {
                                        context.Errorln(ex.Message);
                                    }
                                }

                                if (pspec == null)
                                {
                                    syntaxError = true;
                                    context.Errorln($"invalid parameter: class={type.FullName} method={method.Name} name={parameter.Name}");
                                }
                                else
                                {
                                    paramspecs.Add(pspec);
                                }
                            }
                            pindex++;
                        }

                        #endregion

                        if (!syntaxError)
                        {
                            var cmdNameAttr = method.GetCustomAttribute <CommandNameAttribute>();

                            var cmdName = CheckAndNormalizeCommandName(
                                (cmdNameAttr != null && cmdNameAttr.Name != null) ?
                                cmdNameAttr.Name
                                        : (cmd.Name ?? method.Name));

                            bool registered = true;
                            CommandSpecification cmdspec = null;

                            try
                            {
                                cmdspec = new CommandSpecification(
                                    cmdNamespace,
                                    cmdName,
                                    cmd.Description,
                                    cmd.LongDescription,
                                    cmd.Documentation,
                                    method,
                                    instance,
                                    cmdAliases,
                                    paramspecs);
                            } catch (Exception ex)
                            {
                                context.Errorln($"error in command '{cmdName}' specification: {ex.Message}");
                            }

                            if (cmdspec != null)
                            {
                                if (_commands.TryGetValue(cmdspec.Name, out var cmdlst))
                                {
                                    if (cmdlst.Select(x => x.MethodInfo.DeclaringType == type).Any())
                                    {
                                        context.Errorln($"command already registered: '{cmdspec.Name}' in type '{cmdspec.DeclaringTypeFullName}'");
                                        registered = false;
                                    }
                                    else
                                    {
                                        cmdlst.Add(cmdspec);
                                    }
                                }
                                else
                                {
                                    _commands.Add(cmdspec.Name, new List <CommandSpecification> {
                                        cmdspec
                                    });
                                }


                                if (registered)
                                {
                                    _syntaxAnalyzer.Add(cmdspec);
                                    comsCount++;
                                    // register command Aliases
                                    if (cmdspec.Aliases != null)
                                    {
                                        foreach (var alias in cmdspec.Aliases)
                                        {
                                            context.CommandLineProcessor.CommandsAlias.AddOrReplaceAlias(
                                                context,
                                                alias.name,
                                                alias.text
                                                );
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

            if (registerAsModule)
            {
                if (comsCount == 0)
                {
                    context.Errorln($"no commands found in type '{type.FullName}'");
                }
                else
                {
                    var descAttr    = type.GetCustomAttribute <CommandsAttribute>();
                    var description = descAttr != null ? descAttr.Description : "";
                    _modules.Add(
                        type.FullName,      // key not from assembly but from type
                        new ModuleSpecification(
                            type.FullName,
                            ModuleUtil.DeclaringTypeShortName(type),
                            description,
                            type.Assembly,
                            new ModuleInfo(
                                1,
                                comsCount
                                ),
                            type
                            ));
                }
            }
            return(comsCount);
        }
Esempio n. 3
0
        public ModuleSpecification RegisterModule(
            CommandEvaluationContext context,
            Assembly assembly)
        {
            ModuleSpecification moduleSpecification;

            var moduleAttr = assembly.GetCustomAttribute <ShellModuleAttribute>();

            if (moduleAttr == null)
            {
                context.Errorln($"assembly is not a shell module: '{assembly.FullName}'");
                return(ModuleSpecification.ModuleSpecificationNotDefined);
            }

            var id = assembly.GetCustomAttribute <AssemblyTitleAttribute>()?.Title ??
                     throw new Exception($"module id missing in assembly '{assembly.ManifestModule.Name}' ('AssemblyTitle' attribute missing)");
            var ver = assembly.GetCustomAttribute <AssemblyInformationalVersionAttribute>()?.InformationalVersion ??
                      throw new Exception($"module version missing in assembly '{assembly.ManifestModule.Name}' ('AssemblyInformationalVersion' attribute missing)");
            var modKey = GetModuleLowerId(id, ver);

            if (_modules.ContainsKey(modKey))
            {
                context.Errorln($"module already registered: {modKey} (path={assembly.FullName})");
                return(ModuleSpecification.ModuleSpecificationNotDefined);
            }

            var typesCount  = 0;
            var comTotCount = 0;
            var hooksCount  = 0;

            foreach (var type in assembly.GetTypes())
            {
                // register hooks

                var hookAttr = type.GetCustomAttribute <HooksAttribute>();
                if (hookAttr != null)
                {
                    // module,class owns hooks
                    foreach (var mi in type.GetMethods(BindingFlags.Public | BindingFlags.Instance))
                    {
                        var hook = mi.GetCustomAttribute <HookAttribute>();
                        if (hook != null)
                        {
                            ModuleHookManager.RegisterHook(context, hook.HookName, mi);
                            hooksCount++;
                        }
                    }
                }

                // register commands

                var comsAttr = type.GetCustomAttribute <CommandsAttribute>();

                var comCount = 0;
                if (comsAttr != null && type.GetInterface(typeof(ICommandsDeclaringType).FullName) != null)
                {
                    comCount = ModuleCommandManager.RegisterCommandClass(context, type, false);
                }
                if (comCount > 0)
                {
                    typesCount++;
                }
                comTotCount += comCount;
            }

            // register module

            var descAttr    = assembly.GetCustomAttribute <AssemblyDescriptionAttribute>();
            var description = (descAttr != null) ? descAttr.Description : "";

            _modules.Add(
                modKey,
                moduleSpecification = new ModuleSpecification(
                    modKey,
                    Path.GetFileNameWithoutExtension(assembly.Location),
                    description,
                    assembly,
                    new ModuleInfo(
                        typesCount,
                        comTotCount,
                        hooksCount
                        )
                    ));

            // run module hook init
            ModuleHookManager.InvokeHooks(
                context,
                Hooks.ModuleInit,
                (o) =>
            {
                moduleSpecification.IsInitialized = true;
            }
                );

            return(moduleSpecification);
        }
Esempio n. 4
0
        public ModuleSpecification RegisterModule(
            CommandEvaluationContext context,
            Assembly assembly)
        {
            ModuleSpecification moduleSpecification;

            var moduleAttr = assembly.GetCustomAttribute <ShellModuleAttribute>();

            if (moduleAttr == null)
            {
                context.Errorln($"assembly is not a shell module: '{assembly.FullName}'");
                return(ModuleSpecification.ModuleSpecificationNotDefined);
            }

            // id is the name of the assembly (/!\ should not fit nuget packet id)

            var modKey = _moduleKey(assembly, out var id, out var ver);
            var assKey = _assemblyKey(assembly);

            if (_loadedModules.Contains(assKey))
            {
                throw new Exception($"assembly already loaded: '{assKey}'");
            }

            if (_modules.ContainsKey(modKey))
            {
                context.Errorln($"module already registered: {modKey} (path={assembly.FullName})");
                return(ModuleSpecification.ModuleSpecificationNotDefined);
            }

            var typesCount  = 0;
            var comTotCount = 0;
            var hooksCount  = 0;

            foreach (var type in assembly.GetTypes())
            {
                // register hooks

                var hookAttr = type.GetCustomAttribute <HooksAttribute>();
                if (hookAttr != null)
                {
                    // module,class owns hooks
                    foreach (var mi in type.GetMethods(BindingFlags.Public | BindingFlags.Instance))
                    {
                        var hook = mi.GetCustomAttribute <HookAttribute>();
                        if (hook != null)
                        {
                            ModuleHookManager.RegisterHook(context, hook.HookName, mi);
                            hooksCount++;
                        }
                    }
                }

                // register commands

                var comsAttr = type.GetCustomAttribute <CommandsAttribute>();

                var comCount = 0;
                if (comsAttr != null && type.GetInterface(typeof(ICommandsDeclaringType).FullName) != null)
                {
                    comCount = ModuleCommandManager.RegisterCommandClass(context, type, false);
                }
                if (comCount > 0)
                {
                    typesCount++;
                }
                comTotCount += comCount;
            }

            // register module

            var descAttr    = assembly.GetCustomAttribute <AssemblyDescriptionAttribute>();
            var description = (descAttr != null) ? descAttr.Description : "";

            _modules.Add(
                modKey,
                moduleSpecification = new ModuleSpecification(
                    modKey,
                    Path.GetFileNameWithoutExtension(assembly.Location),
                    description,
                    assembly,
                    new ModuleInfo(
                        typesCount,
                        comTotCount,
                        hooksCount
                        )
                    ));
            _loadedModules.Add(_assemblyKey(assembly));
            _loadedAssemblies.Add(assembly.Location.ToLower());

            // run module hook init
            ModuleHookManager.InvokeHooks(
                context,
                Hooks.ModuleInit,
                HookTriggerMode.FirstTimeOnly,
                (o) =>
            {
                moduleSpecification.IsInitialized = true;
            }
                );

            return(moduleSpecification);
        }