This post contains a lot of code, but I would really appreciate it if you took the some to read and understand it…and hopefully come up with a solution
Let’s assume that I am structuring a network-game where the entities need to be drawn and some of them updated from the server accordingly.
The Drawable class is in charge of drawing the entities on-screen:
class Drawable
{
public int ID { get; set; } // I put the ID here instead of having another
// class that Drawable derives from, as to not
// further complicate the example code.
public void Draw() { }
}
The data that is received from the server implements IData with each concrete IData holding different properties. Let’s say we have the following data that the Player and Enemy will receive:
interface IData
{
int ID { get; set; }
}
class PlayerData : IData
{
public int ID { get; set; }
public string Name { get; set; }
}
class EnemyData : IData
{
public int ID { get; set; }
public int Damage { get; set; }
}
The game entities that should be updateable from the server implement IUpdateable<T> where T is IData:
interface IUpdateable<T> where T : IData
{
void Update(T data);
}
Our entities are thus Drawable and Updateable:
class Enemy : Drawable, IUpdateable<EnemyData>
{
public void Update(EnemyData data) { }
}
class Player : Drawable, IUpdateable<PlayerData>
{
public void Update(PlayerData data) {}
}
So that’s the basic structure of the game.
Now, I need to store a Dictionary of these Drawable and Updateable objects, storing the Drawable‘s ID as the key and a complex object that holds the Drawable and Updateable objects and their remote concrete IData:
class DataHolder<T, T1> where T:Drawable, IUpdateable<T1> where T1:IData
{
public T Entity{ get; set;}
public IData Data{ get; set;}
public DataHolder(T entity, IData data)
{
Entity = entity;
Data = data;
}
}
As an example, say I currently have the following entities:
var p1 = new Player();
var p1Data = new PlayerData();
var e1 = new Enemy();
var e1Data = new EnemyData();
var playerData = new DataHolder<Player, PlayerData>(p1, p1Data);
var enemyData = new DataHolder<Enemy, EnemyData>(e1, e1Data);
I now need to have a Dictionary that holds the entities’ ID as a key (p1.ID and e1.ID) and their DataHolder (playerData and enemyData) and their value.
Something like the following (the below code just shows what I want to do and thus it doesn’t not compile):
Dictionary<int, DataHolder> list = new Dictionary<int, DataHolder>();
list.Add(p1.ID, playerData);
list.Add(e1.ID, enemyData);
How do I construct such a Dictionary?
[Update]
As regards usage, I will then need to be able to do the following:
foreach (var value in list.Values)
{
var entity = value.Entity;
entity.Update(value.Data);
}
I have also tried to change the design of DataHolder to the following:
class DataHolder<T> where T:Drawable, IUpdateable<IData>
{
public T Entity{ get; set;}
public IData Data{ get; set;}
public DataHolder(T entity, IData data)
{
Entity = entity;
Data = data;
}
}
Then I tried something like the following:
var playerData = new DataHolder<Player>(p1, p1Data); //error
But that throws a compile-time error:
The type ‘Player’ must be convertible
to ‘IUpdateable<IData>’ in order
to use it as parameter ‘T’ in the
generic class ‘DataHolder<T>’
For what reason is this thrown? Player implements IUpdateable<PlayerData> and PlayerData implements IData. Is this an issue with variance? And is there any way around it ?
Make your
DataHolderclass implement or inherit a non-generic class or interface, then make a dictionary of that (non-generic) type.