简体   繁体   中英

How do I call a method on a parent and chain the method call down it's inheritance hierarchy in C#?

I have an abstract base class ( BaseMessage ) with a method SerializeProperties that serializes all it's properties into a byte array and holds them in a protected variable of type byte[] .

There is a class inherited from this abstract base class ( BaseCommandMessage ) which is also abstract and introduces a few more properties. I want this class to implement SerializeProperties forcing it to serialize all it's local properties and add it to the byte array.

After that I have a concrete class that inherits from that abstract class ( CommandMessage ) that needs to implement SerializeProperties and serialize it's properties to the byte array.

This can go on for X number of generations but I want to enforce that each class must implement SerializeProperties and I'd like to do all this without using reflection .

Furthermore if I have a statement such as:

BaseMessage message = new CommandMessage();
message.SerializeProperties();

It should serialize the BaseMessage properties, the BaseCommandMessage properties and finally the CommandMessage properties sequentially.

ie call the SerializeProperties method of the BaseMessage class, the SerializeProperties method of the BaseCommandMessage class and finally the SerializeProperties of the CommandMessage class respectively.

I hope that makes sense!

Thanks

ps

I can do this with one generation ie in my base class I have an implemented method called SerializeMyProperties which serializes all it's properties and then calls an abstract or virtual method SerializeProperties which the inheriting class can implement. That way it serializes it's own properties and then serializes the inherited class but I can't go past +2 generations.

Make sure that each class that provides an overload for SerializeProperties first makes a call to base.SerializeProperties . It might be better to change the method to return the bytes, and then augment the array with each generation. This should allow each generation to do what it needs to, and enable future generations to do what they need to.

class BaseMessage
{
    protected virtual byte[] SerializeProperties()
    {
        var bytes = new List<byte>();
        bytes.AddRange(...); // serialize BaseMessage properties
        return bytes.ToArray();
    }
}

class BaseCommandMessage
{
    protected override byte[] SerializeProperties()
    {
        var bytes = new List<byte>(base.SerializeProperties());

        bytes.AddRange(...); // serialize BaseCommandMessage properties
        return bytes.ToArray();
    }
}

class CommandMessage
{
    protected override byte[] SerializeProperties()
    {
        // A call to this method will call BaseCommandMessage.SerializeProperties,
        //   and indirectly call BaseMessage.SerializeProperties

        var bytes = new List<byte>(base.SerializeProperties());

        bytes.AddRange(...); // serialize CommandMessage properties
        return bytes.ToArray();
    }
}

I can do this with one generation ie in my base class I have an implemented method called SerializeMyProperties which serializes all it's properties and then calls an abstract or virtual method SerializeProperties which the inheriting class can implement. That way it serializes it's own properties and then serializes the inherited class but I can't go past +2 generations.

You likely had it, you probably just made a mistake in how you did SerializeMyProperties. Here is the pattern I use. The public class that is exposed to the user is non vitual (this step is not nessesary but it makes it convenient if the base class needs to perform some extra steps on the agragated work, like my call to ToArray() ), it calls a private virtual function where each child calls it's parent's version before it starts to do it's work.

abstract class Foo
{
    public byte[] SerializeProperties()
    {
         var props = new List<byte>();
         SerializeMyProperties(props);
         return props.ToArray();
    }

    private virtual void SerializeMyProperties(List<byte> props)
    {
        byte[] serializedByteArrayForThisInstance;

        //Magic!
         props.AddRange(serializedByteArrayForThisInstance);
    }
}

class Bar : Foo
{
    private virtual void SerializeMyProperties(List<byte> props)
    {
        //Call the Foo's SerializeMyProperties first so it fills the first part of the list
        base.SerializeMyProperties(props);

        byte[] serializedByteArrayForThisInstanceToo;

        //Even More Magic!

         props.AddRange(serializedByteArrayForThisInstanceToo);
    }
}

class Baz : Bar
{
    private virtual void SerializeMyProperties(List<byte> props)
    {
        //Call the Bar's SerializeMyProperties first so it fills the first two parts of the list
        base.SerializeMyProperties(props);

        byte[] iAmRunningOutOfVariableNames;

        //Here Be Dragons!

         props.AddRange(iAmRunningOutOfVariableNames);
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM