我看到了一个明确的情况依赖注入模式。
让我们建立一个简单的例子,用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();
}
}
现在,而是创建一个interface
为Console
功能:
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
。
您可以创建与IOutput
一些测试实现,如以下使用Homework
class
一个测试类:
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()
方法,可以简化所有这些代码,但恕我直言,我认为对这种可能的解决方案的更广泛的观点是有用的。
你不能“绕过”它。代码必须写入,以便在输入重定向时不调用ReadKey()。使用[IsInputRedirected方法](http://stackoverflow.com/a/3453272/17034)。或者指导学生不要使用ReadKey()。或者ReadLine()。教他们如何在Main()的最后一个大括号处设置断点,以便他们不需要这样做会很有用。 –
使用Teensy(或其他任何东西)来模拟键入您的内容的键盘。那么你将不需要重定向输入,所以ReadKey将起作用! – wablab