C #, abstract superclass implementing a specific variable defined by a subclass?

I have a system that performs operations on a variety of Things , this can be considered hardware devices available over the communication channel.

I use a manager design that accepts tasks for a single Things . There are now at least three types of Thing , and they have slightly different properties associated with them. The manager should be aware of these additional properties, since they are necessary for proper operation (some Things should have their own X foo'd instead of Y, etc.).

At the moment, I have a separate manager class for each type of thing. This causes a lot of duplication, as Things are basically similar.

It would be nice if I had an abstract manager that implements significant functionality, and then each particular implementation can provide small additional bits.

Here is a very 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 a particular ThingManager should have ??ThingTask?? either ThingTask or AdvancedThingTask . Then it would be advisable to use additional properties when implementing abstract methods.

Using the interface for ??ThingTask?? will not work, because properties must be declared in the interface, and each of them has different available properties.

I feel like I am missing something very obvious regarding how to do this cleanly, hope someone can help :)

+4
source share
2 answers

use generalizations, not a pure abstract class, matched line by line:

 public abstract class ThingManager<T> where T : ThingTask 

depending on your full implementation. I doubt it will remain abstract.

+3
source

Is there a reason you are not making AdvancedThingTask a subclass of ThingTask?

 public class ThingTask { public virtual string Name { get; set; } public virtual ThingType Type { get; set; } public virtual ThingOperation Operation { get; set; } public virtual void DoThing() { /*Do something associated with ThingTask*/ } } public class AdvancedThingTask : ThingTask { public bool EnableFrobber { get; set; } public override void DoThing() { /*Do something associated with AdvancedThingTask*/ } } 

The only problem I see with is that ThingOperation will need to be declared outside the classes so that it can have all the values ​​or some other solution that will allow the classes to have values ​​that are not specified in the base declaration. This problem may be solved by placing what you want to do as virtual methods in classes.

PS Why do your properties begin with underscores? This is usually reserved for private variables.

0
source

Source: https://habr.com/ru/post/1398651/


All Articles