Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to enforce the existence of a static member in a child class in C#?

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?

like image 262
xeophin Avatar asked Dec 22 '10 13:12

xeophin


1 Answers

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; }
like image 98
Phil Hunt Avatar answered Sep 22 '22 11:09

Phil Hunt