Reputation:
To start, some classes:
public abstract class Component
{
GenericSystem mySystem;
public Component() { mySystem = null;}
public void SetSystem(GenericSystem aSystem) { mySystem = aSystem; }
}
public class PhysicsComponent : Component
{
int pos;
public PhysicsComponent(int x) : base() { pos = x; }
}
public abstract class GenericSystem : List<Component>
{
public Type ComponentType;
public GenericSystem(Type componentType)
{ ComponentType = componentType; }
public void RegisterComponent(c)
{
Add(c);
c.SetSystem(this);
}
}
public class PhysicsSystem : GenericSystem
{
public PhysicsSystem() : base(typeof(PhysicsComponent)) { }
}
public static GenericEngine
{
List<GenericSystem> systems = new List<GenericSystem>();
//... Code here that adds some GenericSystems to the systems ...
public static void RegisterComponent(Component c)
{
foreach(GenericSystem aSystem in systems)
{
Type t = aSystem.ComponentType;
//PROBLEM IS HERE
t c_as_t = c as t;
//
if ( c_as_t != null)
aSystem.RegisterComponent(c);
}
}
}
The error I get is "The type or namespace 't' could not be found."
I want each GenericSystem
to have a Component
type that it wants registered to it. This way, anything registering a new Component c
simply calls GenericEngine.RegisterComponent(c)
and all systems interested in that type of component register it.
Ideally, I'd like to have the code more along the lines of:
//where T must be a child of Component
public abstract class GenericSystem<T> : List<Component> { /... }
public class PhysicsSystem : GenericSystem<PhysicsComponent>
I suspect this isn't a terribly complicated question, and I'm missing something about how C# deals with types (or, more embarrassingly, generics in general) so if it's an easy question, please just point me in the direction of some reading material. Thanks in advance!
Upvotes: 1
Views: 405
Reputation: 660533
Local variable declarations and "as" do not work that way. "t" is an expression that at runtime evaluates to a reference to an object that represents a type. The local decl, and "as" are expecting a program fragment that at compile time names a type.
You're trying to put a cake onto a shelf of cake recipe books; though cakes and cake recipe books are intimately related, they are not the same kind of thing.
If you want to determine if at runtime, the object c is of the type described by the t object, then you can call GetType on c and determine if the two types are either (1) equal, if you demand identity, or (2) compatible, if you merely require one to be compatible with the other.
Ideally, I'd like to have the code more along the lines of:
//where T must be a child of Component
public abstract class GenericSystem<T> : List<Component>
OK, then say that:
public abstract class GenericSystem<T> : List<Component> where T : Component
Looking at your design, other things seem suspicious. Is a generic system actually a kind of list of components, or is it a thing that, among other things, contains a list of components? Use derivation to express "is a kind of" relationships. Use containment to express "container" relationships. A car is not a kind of list of wheels; a car has a list of wheels.
Upvotes: 9
Reputation: 283921
First, you're writing
if ((c as T) != null)
which is simpler
if (c is T)
Then, as Eric points out, these operators need types, not variables containing type metadata. You'll need reflection, like:
if (t.IsAssignableFrom(c.GetType()))
Upvotes: 1