我应该使用构造函数注入还是IoC.Resolve

本文关键字:IoC Resolve 注入 构造函数 我应该 | 更新日期: 2023-09-27 18:22:22

我正在构建非常简单的棋盘游戏(只是为了学习一些新东西)。它将是跨平台的(使用Xamarin编写)。我已经编写了游戏的核心,但我不确定(仍然)应该使用构造函数注入还是IoC解析。现在我使用IoC。解析,然后传递参数。

这是我的密码。我有Game,它有2个依赖项和类型。我有工厂来创建游戏和玩家:

Abc.MyGame.Domain

  • 接口

    public interface IGame
    {
        GameType GameType { get; }
        IGameBoard GameBoard { get; }
        List<IPlayer> Players { get; }
        // Other stuff...
    }
    public interface IGameBoard
    {
        //board stuff...
    }
    public interface IPlayer
    {
        int PlayerId { get; set; }
        PlayerType PlayerType { get; set; }
    }
    
  • 工厂接口

    public interface IGameFactory
    {
        IGame CreateGame(GameType type, IGameBoard board);
    }
    public interface IPlayerFactory
    {
        IPlayer CreatePlayer(PlayerType type, int id);
    }  
    
  • 工厂

    public class GameFactory : IGameFactory
    {
        public IGame CreateGame(GameType type, IGameBoard board)
        {
            switch (type)
            {
                case GameType.SinglePlayer:
                    return new MyGame(type, board,
                        new List<IPlayer> { CreateHuman(1), CreateBot(2) });
                case GameType.TwoPlayers:
                    return new MyGame(type, board,
                        new List<IPlayer> { CreateHuman(1), CreateHuman(2) });
                case GameType.Online:
                    return new MyGame(type, board,
                        new List<IPlayer> { CreateHuman(1), CreateOnlinePlayer(2) });
            }
            return null;
        }
    }
    

然后是API。用户界面使用:

Abc.MyGame.API

public class GameAPI
{
    public IGame CurrentGame { get; set; }
    public IGame CreateGame(IGameFactory gameFactory, GameType type, IBoard board)
    {
        CurrentGame = gameFactory.CreateGame(type, board);
        return CurrentGame;
    }
    // Other stuff, like make move etc...
}

和我的UI:

Abc.MyGame.UI.WinForms

public partial class Form1 : Form
{
    private GameAPI api = new GameAPI();
    IKernel kernel = new StandardKernel();
    public Form1()
    {
        InitializeComponent();
        // Load all dependencies
        var modules = new List<INinjectModule> { new GameModule() };
        kernel.Load(modules);
    }
    private void buttonStartGame(object sender, EventArgs e)
    {
        IGameBoard board = kernel.Get<IGameBoard>(
            new ConstructorArgument("width", 7), 
            new ConstructorArgument("height", 6)
        );
        api.CreateGame(kernel.Get<IGameFactory>(), GameType.TwoPlayers, board);
    }
}

我需要IGame中的IGameBoard。只有那里。我需要为IGame注入棋盘和玩家。

这是我的问题:我真的需要在程序的"前端"解决IGameBoard吗?当有人点击"开始游戏"按钮时,我在UI中解决了这个问题。然后我通过API传递这个板,然后传递给GameFactory,然后传递到Game构造函数(最后!)。在GameFactory内部创建(或解决)IPlayerFactoryIGameBoard是否是一种不良做法?在这种情况下,API.CreateGame将只有type参数?我的意思是,对于特定的GameFactory,只有一个板(每次都一样),所以我不确定我是否需要在一开始就创建板。。。

编辑:MyGame构造函数:

public class MyGame : IGame
{
    public IBoard Board { get; }
    public GameType Type { get; }
    public List<IPlayer> Players { get; }
    public MyGame(GameType type, IBoard board, List<IPlayer> players)
    {
        Type = type;
        Board = board;
        Players = players;
    }
    //...
}

我应该使用构造函数注入还是IoC.Resolve

我真的需要在程序的"前沿"解决IGameBoard问题吗?

是的,依赖关系需要在应用程序的入口点和生存期范围(如果有的话)开始时解决。通常,这是抽象的(就像在ASP.NET MVC中一样),所以您永远不必自己调用kernel.Get<>(或任何其他container.Resolve<>)。在WinForms中没有这样的机制,所以你必须自己解决依赖关系,最好只解决像这样的根依赖关系:

public static class Program
{
    private static void Main()
    {
        var kernel = new StandardKernel();
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(kernel.Get<Form1>());
    }
}

通过在主窗体上放置正确的依赖项(可能包括游戏的工厂),您的应用程序中不需要更多的kernel.Get<>