C# – Passing a List of Choices with Different Arguments

architectural-patternscgame developmentuser interface

I am writing a card game, in which I separated the "Core Logic" of the game from the UI. Communication with the player from the core logic part is done via callbacks which the UI implements and handles (in a separate thread if needed). The core logic library calls these callbacks, the UI handles them, passing an object representing the data that needs to be returned, and returns it.

What I'm currently stuck in is implementing the ability for the Core Logic to give the player a "choice" between possible actions. For example, the core logic might want the player to select from the following 3 game actions:

  • Draw 5 cards from Deck A
  • Draw 2 cards from Deck B
  • Allocate 4 points into bucket 1

The point being that each action can be pretty different from the other. How can I represent this information as an object in C#? I can think of 4 ugly ways…

  1. Just pass a list of strings containing the choice text to the UI and have the UI display them, then the user selects between them:

This is the most simplest (and very tempting) approach, but that would be mixing the UI with the Core Logic, which goes against the main idea behind the design.

  1. Pass an object containing an enum and an object, whose actual type depends on the value of the enum (The enum being something like Draw, Allocate, etc., and the object containing things like the number of cards and which deck for the Draw choice, and the number of points and what bucket for the Allocate command)

But that involves a lot of if statements and typecasting and reflection, among other problems, which is ugly. It also means that I would have to make a separate class for almost every type of choice enum, which is also ugly because each class would just be a list of values.

  1. Pass a dictionary contaning string keys and values, the content of the dictionary depending on the type of choice that one can make.

This will still involve a lot of typecasting and I also lose type safety, but at least I wouldn't have to make a class for every single choice.

  1. Pass an object containing an enum and a dynamic object containing an anonymous type whose fields depend on what the value of the enum is.

This makes handling the stuff in the UI a lot more straightforward and I wouldn't have to make multiple classes, but then I lose type safety and basic checks during compile time..

Is there any sort of pattern that people usually use when facing this problem, or should I just pick my poison and go for it? Perhaps I should rethink my entire approach to the whole thing?

In C, I would probably be using a union of structs for this sort of thing. I'm not sure how I would go about it in C#. Perhaps I'm thinking too much in C?

Best Answer

I'm for 2, but with slight modification. I wouldn't use enum. You can just as fine use GetType(). If you were to add enum to the mix, it would duplicate the type information contained within the object.

On top of that, I would create an Visitor for the Choice class. This will remove the need for reflection and give UI type-safe way to create textual representation for each choice. It will also ensure that when you add new choice type, the compiler will force you to implement all related code, like creating a textual representation for it. And I don't see how having many classes is bad. It is actually good thing, as long as those classes are cohesive.

And I don't think those objects will contain only data. They can very well be objects doing the actual action. Just put Execute() method on them, and they can be the ones drawing the cards from decks or allocating points to buckets.

Related Topic