我正在创建一个类似于输出终端(Unix)或命令行提示符(Windows)的应用程序。我创建了一个字典,其中包含一些函数关键字。但是当我调用这些关键字时,什么也没做。我的程序称为命令行控制(或CLC)。我使用的是.NET Core,适用于所有正在运行的软件(Linux,macOS和Windows)。
我不知道该怎么尝试。功能就是功能。当我调用它时必须执行它。
using System;
using System.Collections.Generic;
using System.Threading;
using System.IO;
namespace CLC
{
class Program
{
static DirectoryInfo maindirectory;
static Dictionary<string, string> keyaction;
static string value;
static void WritePathOfWorkingDirectory(DirectoryInfo directory)
{
if (directory != null)
{
Console.Write("{0}:", directory.FullName);
}
else
{
}
}
static void ProcessAnswer(string[] array)
{
string action = array.GetValue(0).ToString();
value = array.GetValue(1).ToString();
string c = keyaction[action];
Console.Write(c);
}
static string ListFiles()
{
foreach(var file in maindirectory.GetFiles())
{
Console.WriteLine(file.Name);
}
return "ok";
}
static string ListDirectories()
{
foreach(var directory in maindirectory.GetDirectories())
{
Console.WriteLine(directory);
}
return "ok";
}
static void MainProgramm()
{
WritePathOfWorkingDirectory(maindirectory);
string data = Console.ReadLine();
var arry = data.Split(' ');
ProcessAnswer(arry);
Thread repeat = new Thread(MainProgramm);
repeat.Start();
}
static void Main(string[] args)
{
maindirectory = new DirectoryInfo("C:/Users");
keyaction = new Dictionary<string, string>();
keyaction.Add("lf", ListFiles());
keyaction.Add("ld", ListDirectories());
Console.Clear();
maindirectory = new DirectoryInfo("C:/Users");
Thread thread = new Thread(new ThreadStart(MainProgramm));
thread.Start();
}
}
}
预期的结果是执行键所指示的操作:例如,如果键入ld
(列表目录),则应执行列表目录功能。但是我什么都没有!该程序只是重复自己。
答案 0 :(得分:0)
在“方法”名称后加上括号时,将调用该方法。因此,不是传递函数作为Dictionary值,而是传递调用该函数的结果。您需要获取要调用的函数的引用,然后调用它。
您的Main方法应如下所示:
CameraX
和关键动作应这样声明:
static void Main(string[] args)
{
maindirectory = new DirectoryInfo("C:/Users");
keyaction = new Dictionary<string, Func<string>>(); // changed this to an Func instead of a string
keyaction.Add("lf", ListFiles); // notice I removed the parentheses here
keyaction.Add("ld", ListDirectories); // and here
Console.Clear();
maindirectory = new DirectoryInfo("C:/Users");
Thread thread = new Thread(new ThreadStart(MainProgramm));
thread.Start();
}
然后,在您的ProcessAnswer方法中,您需要通过在Dictionary中对该函数的引用来调用该函数:
static Dictionary<string, Func<string>> keyaction; // a Func<string> is a function that returns a string and takes no arguments
这应该给您预期的结果。
在当前状态下,程序的方法仅被调用一次,然后在看到输出之前先清除控制台,所以看起来只要输入命令,程序就说“确定”。
答案 1 :(得分:0)
主要问题是您要在字典中存储string
值,而不是函数本身,因此,添加函数时,您要添加它们的立即返回值(在提示用户之前输入)。
相反,字典值应为Func<string>
,然后您可以根据需要.Invoke
。
此外,您似乎没有在验证用户条目。我们可以使用TryGetValue
作为用户输入内容,以确保他们输入了有效的命令(如果字典中存在该命令)。如果不是,我们可以告诉他们他们的输入无效。
此外,在访问数组值时,您首先应确保要访问的索引有效(如果用户仅输入一个命令,例如"lf"
,而没有任何值,那么您将无法访问数组索引[1]
,因为它不存在。
而且,即使用户确实输入了路径,您也似乎将其存储在value
中,但从未使用过。因此,我修改了ListFiles
和ListDirectories
方法,以将该值视为路径,如果存在,请从指定的路径中列出文件或目录。
尝试以下代码进行更改:
public class Program
{
private static DirectoryInfo _maindirectory = new DirectoryInfo("C:\\Users");
private static Dictionary<string, Func<string>> _keyaction =
new Dictionary<string, Func<string>>
{
{"lf", ListFiles},
{"ld", ListDirectories},
{"cd", ChangeDirectory},
{"exit", Exit}
};
private static string _value;
private static void DisplayPrompt(FileSystemInfo directory)
{
Console.Write($"{directory?.FullName ?? "[cmd]"}: ");
}
private static void ProcessAnswer(IReadOnlyList<string> array)
{
var action = array.Count > 0 ? array[0] : string.Empty;
_value = array.Count > 1 ? array[1] : null;
Func<string> method;
_keyaction.TryGetValue(action, out method);
if (method == null)
{
WriteError($"Unknown command: {action}");
}
else
{
Console.WriteLine(_keyaction[action].Invoke());
}
}
private static string ListFiles()
{
var dir = Directory.Exists(_value) ? new DirectoryInfo(_value) : _maindirectory;
foreach (var file in dir.GetFiles())
{
Console.WriteLine(file.Name);
}
return "ok";
}
private static string ListDirectories()
{
var dir = Directory.Exists(_value) ? new DirectoryInfo(_value) : _maindirectory;
foreach (var directory in dir.GetDirectories())
{
Console.WriteLine(directory);
}
return "ok";
}
private static string ChangeDirectory()
{
if (Directory.Exists(_value))
{
_maindirectory = new DirectoryInfo(_value);
}
else if (Directory.Exists(Path.Combine(_maindirectory.FullName, _value)))
{
_maindirectory = new DirectoryInfo(
Path.Combine(_maindirectory.FullName, _value));
}
else
{
WriteError("Directory not found.");
}
return "ok";
}
private static void WriteError(string message)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(message);
Console.ResetColor();
}
private static string Exit()
{
Environment.Exit(0);
return "ok";
}
private static void Main()
{
while (true)
{
DisplayPrompt(_maindirectory);
ProcessAnswer(Console.ReadLine()?.Split(' '));
}
}
}