For a tile-based game I'm using different classes to describe the behaviour of the different tile types. They (obviously) derive from a base class. Now I have the problem that sometimes I need to figure out whether the player has enough funds to pay for an upgrade to a certain tile type.
Since the cost of a tile type remains the same all the time, it would seem to make sense to make that static. Unfortunately, C# does not seem to allow the use of abstract classes or interfaces to enforce the existence of such a static field in a child class.
My "solution" was to get this data using reflection, but it seems to me rather ugly and potentially dangerous, since I might forget the static field in one of the child classes, which would bring down the whole thing …
The following code snippet is what I currently have; AllowedUpdates
is a List<System.Type>
containing the types a tile can be upgraded to.
foreach (Type t in AllowedUpdates) {
// Get the Action Point Cost
FieldInfo fi = t.GetField ("actionPointCost", BindingFlags.NonPublic | BindingFlags.Static);
int cost = (int)fi.GetValue (null);
// Check for any requirements
bool requirementsFulfilled;
try {
// Get the static method that checks the necessary requirements.
MethodInfo mi = t.GetMethod ("CheckRequirements", new Type[] { typeof(Dictionary<string, ProtoObject>) });
object[] arguments = { neighbourFields };
// Invoke this method
object returnValue = mi.Invoke (null, arguments);
requirementsFulfilled = (bool)returnValue;
} catch (ArgumentNullException) {
// This type has no special requirements, pass it.
requirementsFulfilled = true;
} catch (NullReferenceException) {
// No requirements needed, pass it.
requirementsFulfilled = true;
}
}
There must be a better way to do that. Is there a design pattern I overlooked?
You cannot enforce, either by an abstract base class or an interface, the existence of a static
member on any derived class.
Reflection is not your best bet here. Reconsider your usage of static
classes in this case. You might make the cost of a tile type an abstract
read-only property. Derived classes will be forced to implement the property.
public abstract int ActionPointCost { get; }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With