Given basetype A
And three derived types
B : A
C : A
D : A
I have a project P.
I want a List to represent occurrences of A in P.
There is a strategy for extracting Bs from P, which I want to be part of class B.
There is a strategy for extracting Cs from P, which I want to be part of class C.
etc.
I want them all to be listed in one big List.
I want to later be able to add a class E : A, touching as little as possible. It would be cool to have a virtual static Factory method on A accepting instance of P as a parameter, which would polymorphically run all static overloads in the derived classes where for example the overload in C would extract Cs from P and put them in List.
Of course, no such thing as a virtual static method exists in C#.
I can’t immediately see how to implement this so that it would be possible to add classes D:A and E:A without touching the base class or some continuously updated “God-method” factory method with a concrete dependency to every derived type.
It’s kinda late here, so I may be missing something obvious.
Your thoughts?
EDIT:
My specific case is that I have a process plant control system consisting of control modules. I want to be able to recognize certain higher level constructs such as control loop, feedback tuning etc. The logic for recognizing and managing these constructs is specific to the individual construct type in question. In short, I want to bundle the code for identifying and for handling constructs.
Let’s consider an analogy. I have a text document. In it there are types of words. Word is the “base” type “A”. The text document is the “P” project. I can implement the word types “noun” and “verb”. The way in which a “noun” is identified within the text is specific to “noun” and the code should. The List becomes longer as more and more types are implemented and thusly identified within the text.
To me, it makes sense to implement this within the noun class as:
static function IEnumerable<noun> IdentifyAll (P project)
And do a
CompleteWordList.AddRange(noun.IdentifyAll(p));
During initialization, but this creates a dependency to the specific “noun” type from the central initialization/factory method. It would then be difficult to add more word classes without touching it. As I’m writing this, I feel myself sort of leaning towards MEF.
This is a simple example. Maybe “phrase” or something would be a more appropriate analogy for the base type, but it’ll have to do for now.
Even though these projects are networks of connected control nodes with inspectable properties (and not a text document as such), it very much feels like a parser. It would be good if there is some general solution that eludes me.
Okay, I think I get it now. If I understand, you want to take a an object of a type derived from
Aand determine its actual type (sayB), but without the factory knowing how to classify it asB. Then you should be able to introduce any number of subtypes ofAin future without having to modify the factory for each new type.Someone has know how to get from
AtoB. If it isn’t the factory, then it must beBitself. I see you’ve gone down this path and thought “I need a virtual factory method so that each subtype of A can provide the specification to identify itself.”As you said, virtual static methods don’t exist so you can’t do it how you were thinking. But why not use an instance method?
As long as the project contains a list of all known subtypes, it can simply iterate through these types, creating instances of them and asking them “is this object one of you?”. And if it says “yes”, you can then ask it “give me an instance of you equivalent to this base type instance”. (That sounds inefficient; in practice of course you could just keep one “factory instance” of each type alive so you don’t have to keep recreating them.)
A contrived example using something like your word analogy:
Output:
Now when you want to add a new word type, the only code you have to add is:
You’ll notice that
ColorWordis a subtype ofUntypedWordbutNumberWordisn’t. Word types don’t have to share a common base type as long as they implement IWord.Obviously this is a ridiculous example but it shows how each subtype owns the logic to classify itself based on properties of a given object of the common supertype (or common interface), and it knows how to create an instance of itself based on the given object.
So now the
WordList(yourP) class never has to be updated to accommodate new word types. You just need to tell it about all the types at runtime.And you could write your
IdentifyAll(WordList sentence)method, only it would be an instance method instead of static.