vendredi 10 août 2018

Scalable owner interface

I am designing a simple city simulation in C# in which a city is a class. The city has a number of systems like a RoadSystem and TrafficSystem which are also classes. The City class aggregates instances of the above classes.

class City: ICity
{
    RoadSystem.IRoadSystem       m_roadSystem;
    TrafficSystem.ITrafficSystem m_trafficSystem;
}

Example 'system' code:

class SimpleRoadSystem : RoadSystem.IRoadSystem
{
    public SimpleRoadSystem(ICity owner)
    {
    }           
}

The systems as well as the city itself have interfaces to allow alternate implementations as usual.

The classic problem I have is when instantiating the systems. Since the systems are owned by the city class I can pass a ICity instance to them. The ICity interface can be used by the system class to pull any required data from the owning city class. However this ties the SimpleRoadSystem to work with cities only. But in reality a road system is a generic idea, it can be used to implement the roads for a region or in a town which may have different interfaces. Basically tying the owner of the RoadSystem to be a City only, feels restrictive.

So the other idea is to have a IRoadSystemOwner interface between the city and the RoadSystem, which is implemented by the City.

class City: ICity, IRoadSystemOwner, ITrafficSystemOwner,......
{
    RoadSystem.IRoadSystem       m_roadSystem;
    TrafficSystem.ITrafficSystem m_trafficSystem;
}

class SimpleRoadSystem : RoadSystem.IRoadSystem
{
    public SimpleRoadSystem(IRoadSystemOwner owner)
    {
    }           
}

But this does not scale. The city can have any number of systems. Its actually a list thats loaded at runtime. So if the city has 10 different systems it needs, it will need to anticipate that beforehand and implement 10 different owner interfaces!!

Basically I am trying to figure out how to allow the RoadSystem owned class to have a owner which has a known owner interface for sure! But not implement this idea via non-scalable inheritance. This should allow the owned class to pull required information from its owner. It should scale well as a city can have any number of systems thats decided at runtime from data.

The way I see it dynamic casting or a generic property system seems to work. The RoadSystem class could try to cast the owner instance to a ICity or a ITown or IRegion and see which succeeds. Or the owner has a getProperty(key) function which returns a generic object reference which can be cast to the concrete class to get to the actual data like say:

object obj = owner.getProperty("Map")
IMap map = obj as IMap;
if (map == null)
{                
    throw new System.ArgumentException("The map could not be retrieved from owner", "original");
}

Is there any other way than using dynamic casts?

Aucun commentaire:

Enregistrer un commentaire