当输入被重定向时,我可以绕过Console.ReadKey()问题吗?
本文关键字:ReadKey Console 问题 输入 重定向 我可以 | 更新日期: 2023-09-27 18:17:32
我是一名c#教师,我为我的学生写了一些自动的HW检查器。学生们编写c#控制台应用程序。我的HW检查器基于输入重定向,所以我可以在我自己生成的输入上测试他们的代码。
问题是学生有时用Console.ReadKey()
指令结束他们的程序(他们这样做只是为了在F5 - Debug下运行程序时使执行窗口不关闭)。Console.ReadKey()
在输入重定向下运行时崩溃,有以下例外:
系统。InvalidOperationException:当应用程序没有控制台或控制台输入已从文件重定向时,无法读取键。
我有任何方法来"绕过"这个问题(不改变学生的代码)?也许告诉Console
忽略ReadKey
的指令?
我清楚地看到了依赖注入模式。
让我们构建一个简单的例子,Read
, ReadLine
和WriteLine
功能的多态:你的学生必须写一个作业,其中Console.ReadLine()
中给出的数字必须被解析为int
并返回到Console
窗口。
学生通常会这样写:
class Program
{
static void Main(string[] args)
{
var stringValue = Console.ReadLine();
int number;
if (int.TryParse(stringValue, out number))
Console.WriteLine($"The double of {number} is {number * 2}");
else
Console.WriteLine($"Wrong input! '{stringValue}' is not an integer!");
Console.Read();
}
}
现在,为Console
功能创建一个interface
:
public interface IOutput
{
void Read();
string ReadLine();
void WriteLine(string text);
}
学生必须创建一个Homework
class
来封装所有必需的作业代码,使用IOutput
实例,如下所示:
public class HomeWork
{
private IOutput _output;
public HomeWork(IOutput output)
{
_output = output;
}
public void Run()
{
_output.WriteLine("Give me an integer:");
var stringValue = _output.ReadLine();
int number;
if (int.TryParse(stringValue, out number))
_output.WriteLine($"The double of {number} is {number * 2}");
else
_output.WriteLine($"Wrong input! '{stringValue}' is not an integer!");
_output.Read();
}
}
Main
变为:
static void Main(string[] args)
{
var h = new HomeWork(new ConsoleOutput());
h.Run();
}
你也给他们ConsoleOutput
class
:
public class ConsoleOutput : IOutput
{
public void Read()
{
Console.Read();
}
public string ReadLine()
{
return Console.ReadLine();
}
public void WriteLine(string text)
{
Console.WriteLine(text);
}
}
所以使用它而不是直接调用Console.Read()
等
学生必须传递给你的不是整个Application
,而是Homework
class
。
您可以创建一个使用Homework
class
和IOutput
的一些测试实现的测试类,如下所示:
public abstract class TestOutput : IOutput
{
public TestOutput()
{
Outputs = new List<string>();
}
public void Read()
{
//do nothing?
}
public abstract string ReadLine();
public void WriteLine(string text)
{
Outputs.Add(text);
}
public List<string> Outputs { get; set; }
}
public class TestOutputWithAValidNumber : TestOutput
{
public TestOutputWithAValidNumber(int value)
{
Value = value;
}
public override string ReadLine()
{
return Value.ToString();
}
public int Value { get; }
}
public class TestOutputWithNotValidNumber : TestOutput
{
public TestOutputWithNotValidNumber(string value)
{
Value = value;
}
public override string ReadLine()
{
return Value;
}
public string Value { get; }
}
测试类可以像这样:
[TestClass]
public class TestOutputClass
{
[TestMethod]
public void TestGoodNumber()
{
var testOutput = new TestOutputWithAValidNumber(1234);
var h = new HomeWork(testOutput);
h.Run();
Assert.AreEqual(1234, testOutput.Value);
Assert.AreEqual("Give me an integer:", testOutput.Outputs[0]);
Assert.AreEqual("The double of 1234 is 2468", testOutput.Outputs[1]);
}
[TestMethod]
public void TestWrongNumber()
{
var testOutput = new TestOutputWithNotValidNumber("foo");
var h = new HomeWork(testOutput);
h.Run();
Assert.AreEqual("foo", testOutput.Value);
Assert.AreEqual("Give me an integer:", testOutput.Outputs[0]);
Assert.AreEqual("Wrong input! 'foo' is not an integer!", testOutput.Outputs[1]);
}
}
如果您只需要包装Console.Read()
方法,请随意简化所有这些代码,但恕我直言,我认为对这种可能的解决方案的更广泛的看法将是有用的。
如果可执行文件是IL格式,您可以创建一个使用ILDASM的简单应用程序。
关键是:用ILDASM将可执行文件反汇编成一个文本文件/流,查找对Console.Read
的任何调用并删除它,然后重新编译并运行。