I have a system that performs operations on lots of Things
, these can be considered to be hardware devices accessible over a communication channel.
I use a manager construct that accepts tasks for single Things
. Now, there are at least three types of Thing
and they have slightly different properties associated with them. The manager must know about these extra properties as they are needed to perform any operation correctly (some Things
must have their X foo'd instead of their Y etc...).
At the moment I have separate manager class for each type of thing. This causes a good deal of duplication as the Things
are mostly similar.
It would be good if I could have an abstract manager that implements a good deal of the functionality and then each concrete implementation can supply the little extra bits.
Here is a greatly simplified example:
public abstract class ThingManager
{
private ConcurrentDictionary<Guid, ??ThingTask??> _ThingTaskQueue;
public virtual AddNewThingTask(<params>)
{
??ThingTask?? NewTask = new ??ThingTask??(<params>);
_ThingTaskQueue.Add(NewTask);
Monitor.Pulse(_NewDataToProcess);
}
/* Implemented by the concrete, will depend on the type of ??ThingTask?? */
public abstract GetSomeTaskParameterForAThing(Guid thingID)
}
public class ThingTask
{
public enum ThingOperation
{
Foo,
Bar
};
public String Name { get; set; };
public ThingType Type { get; set; };
public ThingOperation Operation { get; set; }
}
public class AdvancedThingTask
{
public enum ThingOperation
{
Foo,
Bar,
Baz
};
public String Name { get; set; };
public ThingType Type { get; set; };
public ThingOperation Operation { get; set; }
public Boolean EnableFrobber { get; set; }
}
As you can see I need some way, when defining the concrete ThingManager
to have ??ThingTask??
be either a ThingTask
or an AdvancedThingTask
. It would then be up to the concrete to make use of the extra properties when implementing the abstract methods.
Using an interface for ??ThingTask??
wouldn't work because the properties would have to be declared in the interface and each one has different properties available.
I get the feeling I'm missing something very obvious as to how to do this cleanly, hopefully someone can help :)