咨询UI向Engine项目GameSession类传递用户输入字符串的方案
解决UI向Engine的GameSession传递用户输入的方案
我来给你几个实用的解决方案,都是针对这种单向引用(UI引用Engine,Engine不引用UI)场景的解耦思路,你可以根据项目复杂度选择合适的:
方案1:直接调用GameSession的公开方法(最简单场景)
如果UI已经能获取到GameSession的实例(因为UI引用Engine,所以可以直接创建或从Engine的入口类获取),这是最直接的方式:
Engine项目的GameSession类
public class GameSession { // 公开接收输入的方法,Engine内部实现处理逻辑 public void ProcessUserInput(string input) { // 这里写你的输入处理逻辑 Console.WriteLine($"GameSession received input: {input}"); } }
UI项目的Button_Click事件处理
// 持有GameSession实例(可以在UI初始化时创建或从外部注入) private GameSession _gameSession; public YourUIForm() { InitializeComponent(); _gameSession = new GameSession(); } private void SubmitButton_Click(object sender, EventArgs e) { string userInput = YourInputTextBox.Text; if (!string.IsNullOrWhiteSpace(userInput)) { // 直接调用GameSession的方法传递输入 _gameSession.ProcessUserInput(userInput); YourInputTextBox.Clear(); } }
这个方案完全满足你的需求,Engine不需要知道UI的任何细节,只需要提供公开的输入处理方法即可。
方案2:使用委托/事件实现反向通知(灵活扩展场景)
如果希望GameSession可以主动订阅输入事件,或者后续有多个组件需要响应输入,用事件/委托更灵活:
Engine项目的GameSession类
public class GameSession { public GameSession() { // 可以在这里绑定内部的输入处理逻辑 UserInputReceived += HandleUserInput; } // 定义输入事件 public event Action<string> UserInputReceived; // 内部的输入处理逻辑 private void HandleUserInput(string input) { Console.WriteLine($"Processed input: {input.ToUpper()}"); } // 可选:封装事件触发逻辑,避免外部直接调用事件 public void TriggerInput(string input) { UserInputReceived?.Invoke(input); } }
UI项目的Button_Click事件处理
private GameSession _gameSession; public YourUIForm() { InitializeComponent(); _gameSession = new GameSession(); } private void SubmitButton_Click(object sender, EventArgs e) { string userInput = YourInputTextBox.Text; if (!string.IsNullOrWhiteSpace(userInput)) { // 直接触发GameSession的事件 _gameSession.UserInputReceived?.Invoke(userInput); // 或者调用封装的触发方法 // _gameSession.TriggerInput(userInput); YourInputTextBox.Clear(); } }
这种方式让GameSession掌握输入处理的主动权,UI只负责传递输入信号,耦合度更低。
方案3:使用抽象接口解耦(复杂/可测试场景)
如果你的项目需要扩展性(比如后续可能替换UI、或者需要单元测试GameSession),用抽象接口是最佳实践:
Engine项目定义抽象接口
// 定义输入处理的抽象接口,Engine只依赖这个接口 public interface IInputHandler { void ProcessInput(string input); }
Engine项目的GameSession类
public class GameSession { private IInputHandler _inputHandler; // 通过构造函数注入接口实例(依赖注入思想) public GameSession(IInputHandler inputHandler) { _inputHandler = inputHandler; } // 或者提供设置方法 public void SetInputHandler(IInputHandler inputHandler) { _inputHandler = inputHandler; } }
UI项目实现接口
// UI实现Engine定义的接口,处理UI到GameSession的输入传递 public class UIInputHandler : IInputHandler { private readonly GameSession _gameSession; public UIInputHandler(GameSession gameSession) { _gameSession = gameSession; } public void ProcessInput(string input) { // 可以在这里添加UI专属的输入预处理(比如去空格、格式校验) string cleanedInput = input.Trim(); // 调用GameSession的核心处理逻辑 _gameSession.ProcessUserInput(cleanedInput); } }
UI项目的Button_Click事件处理
private GameSession _gameSession; private IInputHandler _inputHandler; public YourUIForm() { InitializeComponent(); _gameSession = new GameSession(); _inputHandler = new UIInputHandler(_gameSession); } private void SubmitButton_Click(object sender, EventArgs e) { string userInput = YourInputTextBox.Text; if (!string.IsNullOrWhiteSpace(userInput)) { _inputHandler.ProcessInput(userInput); YourInputTextBox.Clear(); } }
这个方案彻底解耦了Engine和UI,Engine完全不依赖任何UI相关代码,非常适合大型项目或者需要单元测试的场景。
内容的提问来源于stack exchange,提问作者Domica




