Question

What is the best way to implement a strategy for the constructor of a template/abstract class in C#? I have several classes which are all based on parsing a string inside the constructor. The parsing is done in a static method which creates list of key value pairs and is common for all classes, but some fields are also common for all classes - thus I use a abstract template class.

The problem is that I do not see a way to inherite the implementation of the constructor of the abstract base class. Otherwise I would implement the constructor strategy in the base class and would force the handling of the lists inside some abstract methods.

Edit: Added Not working code for the template class

public abstract class XXXMessageTemplate 
{
    public XXXMessageTemplate(string x) // implementation for the constructor 
   {
       Parse(x);//general parse function
       CommonFields();//filling common properties
       HandlePrivateProperties();//fill individual properties
       HandlePrivateStructures();//fill individual structures
    }
    abstract void HandlePrivateProperties();
    abstract void HandlePrivateStructures();
}

The actual messages should not implement any constructor and only implement the HandlePrivateProperties and HandlePrivateStructures functions.
Was it helpful?

Solution

If you want the logic of the base class constructor to run in the derived class, you'd normally just call up to it:

 public Derived(...) : base(...)
 {
     // ...
 }

The base class can call abstract/virtual methods during the constructor, but it's generally frowned upon as the derived class's constructor body will not have been executed yet. (You'd want to document this really emphatically.)

Does this answer your question? I'm not entirely sure I understand the issue - some pseudo-code would help.

EDIT: The derived classes have to implement constructors. Constructors aren't inherited. If you don't specify any constructor, the compiler will provide a parameterless constructor which calls a base parameterless constructor. However, you can easily write a constructor with the same signature and just call the base class constructor:

public Derived(string x) : base(x)
{
    // Base constructor will do all the work
}

OTHER TIPS

Provide a constructor for the base class and use it in the derived classes:

abstract class Base {
     // ...
     protected Base(string commonField) {
        CommonField = commonField;
     }
}

class Derived1 : Base {
     public Derived1(string commonField, string specificField) : base(commonField) {
        SpecificField = specificField;
     }
}

I am not 100% sure I understand the question fully, but do you mean that you want your subclasses to pass a literal string to the base, as in this example?

public class MyMessage : XXXMessageTemplate
{
    public MyMessage() : base("MyMessage String")
    {
    }

    public override void HandlePrivateProperties()
    {
        // ...
    }

    public override void HandlePrivateStructures()
    {
        // ...
    }
}

As I can see the problem is in Parse(...) method. Not in the method itself but in his existence. You have some raw data (string x) which must be converted into structured data (key value pairs) before use to construct objects. So you need somehow pass structured data into base and child constructors. I see 3 approaches:

  1. Parse data in base class and use protected base property to pass it to childs.
  2. Parse data before calling constructor.
  3. Parse data in place of usage.

1 You may extend an Mehrdad answer via additional protected property which holds parsed args. Something like:

abstract class Base {
     protected ParsedData ParsedData;
     // ...
     protected Base(string x) {
        ParsedData = Parse(x);
        CommonFields(); //initialize common fields using ParsedData
     }
}

class Derived1 : Base {
     public Derived1(string x) : base(x) {
        DerivedFields(); //initialize specific fields using ParsedData
     }
}

2 Or you can pass pre parsed string into constructor:

abstract class Base {
     protected ParsedData ParsedData;
     // ...
     public static ParsedData Parse(string x)
     {
        //Parse x here...
     }

     protected Base(ParsedData data) {
        CommonFields(data); //initialize common fields using data
     }
}

class Derived1 : Base {
     public Derived1(ParsedData data) : base(data) {
        DerivedFields(data); //initialize specific fields using data
     }
}

3 Or parse in place of usage:

abstract class Base {
     // ...
     protected Base(string x) {
        var data = Parse(x);
        CommonFields(data); //initialize common fields using data
     }
}

class Derived1 : Base {
     public Derived1(string x) : base(x) {
        var data = Parse(x);
        DerivedFields(data); //initialize specific fields using data
     }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top