C#IoC:实现条件注入

时间:2015-11-07 18:26:56

标签: c# .net dependency-injection inversion-of-control

我想创建一个简单的游戏并使用一个IoC容器。每个游戏都有玩家,所以我想将它们注入Game课程。问题是,可能会有不同类型的球员。第一个玩家将永远是人类(设备所有者;)),但他的对手:人类(玩和传球),Bot或在线(人类,但通过互联网玩)。

这是代码。有不同的球员:

public class Human : IPlayer
{
    public int Id { get; set; }
    public string Name { get; set; }
    public PlayerType Type { get; set; }
}

public class Bot : Human
{
}

public class OnlinePlayer : Human
{
}

public interface IPlayer
{
    int Id { get; set; }
    string Name { get; set; }
    PlayerType Type { get; set; }
}

Game类:

public class Game : IGame
{
    public GameType Type { get; private set; }
    public List<IPlayer> Players { get; private set; }

    public Game(GameType type, List<IPlayer> players)
    {
        Type = type;
        Players = players;
    }
}

public interface IGame
{
    GameType Type { get; }
    List<IPlayer> Players { get; }
}

正如您所看到的,我在Game的容器中注入了玩家列表。这是我的问题:

如果遇到差异类型List<IPlayer>,我该如何解决GameType

如果GameType =单人游戏 - &gt;注入人类和机器人

如果GameType =通过和播放 - &gt;注入人与人

如果GameType =在线游戏 - &gt;注入Human和OnlinePlayer

2 个答案:

答案 0 :(得分:4)

没有理由让它变得更加复杂。您可以添加类似in an Abstract Factory的内容:

if (gameType == GameType.Single)
    return new Game(
        GameType.Single,
        new List<IPlayer> { CreateHuman(); CreateBot() });
else if (gameType == GameType.PassAndPlay)
    return new Game(
        GameType.PassAndPlay,
        new List<IPlayer> { CreateHuman(); CreateHuman() });
else
    return new Game(
        GameType.Online,
        new List<IPlayer> { CreateHuman(); CreateOnlinePlayer() });

答案 1 :(得分:2)

你可以使用Ninject,我在我工作的一些项目中使用这种方法, 并且非常简单,请参阅Ninject项目网站:https://github.com/ninject/Ninject/wiki/Contextual-Binding

关于你的评论我的建议是在实现IGame interface`的具体类中选择游戏类型,参见示例:

public interface IGame
{
    GameType Type { get; }
    ReadOnlyCollection<IPlayer> Players { get; }
}

public class GameSingle : IGame
{
    public GameSingle(List<IPlayer> players)
    {
        Players = players.AsReadOnly();
    }

    public GameType Type => GameType.Single;
    public ReadOnlyCollection<IPlayer> Players { get; }
}

public class GameOnline : IGame
{
    public GameOnline(List<IPlayer> players)
    {
        Players = players.AsReadOnly();
    }

    public GameType Type => GameType.Online;
    public ReadOnlyCollection<IPlayer> Players { get; }
}

public class GamePlayAndPass : IGame
{
    public GamePlayAndPass(List<IPlayer> players)
    {
        Players = players.AsReadOnly();
    }

    public GameType Type => GameType.PassAndPlay;
    public ReadOnlyCollection<IPlayer> Players { get; }
}

现在在ninject的模块中:

        Kernel.Bind<IPlayer>().To<Bott>().WhenInjectedExactlyInto<GameSingle>();
        Kernel.Bind<IPlayer>().To<OnlinePlayer>().WhenInjectedExactlyInto<GameOnline>();
        Kernel.Bind<IPlayer>().To<Human>().WhenInjectedExactlyInto<GamePlayAndPass>();
        Kernel.Bind<IPlayer>().To<Human>();

然后你只需要定义注入IGame具体类XD的时间和地点。