当输入被重定向时,我可以绕过 Console.ReadKey() 问题吗?
Can I bypass Console.ReadKey() issue when input is redirected?
我是一名 C# 老师,我为我的学生编写了一些自动化硬件检查器。
学生编写 C# 控制台应用程序。我的硬件检查器基于输入重定向,因此我可以在我自己生成的输入上测试他们的代码。
问题是学生有时会用Console.ReadKey()
指令结束他们的程序(他们这样做只是为了让执行window在他们运行F5下的程序时不关闭-调试)。 Console.ReadKey()
在输入重定向下 运行 时崩溃,但出现以下异常:
System.InvalidOperationException: Cannot read keys when either application does not have a console or when console input has been redirected from a file.
我有什么办法可以解决"bypass"这个问题(不改变学生代码)?也许告诉 Console
忽略 ReadKey
指令?
我看到了依赖注入模式的明确案例。
让我们构建一个简单的示例,使用多态的 Read
、ReadLine
和 WriteLine
功能:您的学生必须写一份家庭作业,其中 Console.ReadLine()
中给出的数字必须解析为 int
并返回到 Console
Window.
通常学生会这样写:
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
。
您可以创建一个测试 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; }
}
测试class可以是这样的:
[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 将可执行文件反汇编为文本 file/stream,查找对 Console.Read
的任何调用并将其删除,然后重新编译它并 运行.
我是一名 C# 老师,我为我的学生编写了一些自动化硬件检查器。 学生编写 C# 控制台应用程序。我的硬件检查器基于输入重定向,因此我可以在我自己生成的输入上测试他们的代码。
问题是学生有时会用Console.ReadKey()
指令结束他们的程序(他们这样做只是为了让执行window在他们运行F5下的程序时不关闭-调试)。 Console.ReadKey()
在输入重定向下 运行 时崩溃,但出现以下异常:
System.InvalidOperationException: Cannot read keys when either application does not have a console or when console input has been redirected from a file.
我有什么办法可以解决"bypass"这个问题(不改变学生代码)?也许告诉 Console
忽略 ReadKey
指令?
我看到了依赖注入模式的明确案例。
让我们构建一个简单的示例,使用多态的 Read
、ReadLine
和 WriteLine
功能:您的学生必须写一份家庭作业,其中 Console.ReadLine()
中给出的数字必须解析为 int
并返回到 Console
Window.
通常学生会这样写:
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
。
您可以创建一个测试 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; }
}
测试class可以是这样的:
[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 将可执行文件反汇编为文本 file/stream,查找对 Console.Read
的任何调用并将其删除,然后重新编译它并 运行.