Need 'dynamic' which unity doesn't have. Need alternative.

So I have this use case where I need to pass ‘this’ from an abstract superclass with the internal type. See example:

using System;

class Program {
    public static void Main(string[] argv) {
        new SubClass().Init();
        while (true) { /* Keeps console open */ }
    }
}

abstract class SuperClass {

    private MyNetwork network = new MyNetwork();

    public virtual void Init() {
        network.Add(this);
        network.Add(this as dynamic);

        // Intent -> network.Add(this as GetType());
    }
}

// One of multiple subclasses
class SubClass : SuperClass {

    public override void Init() {
        base.Init();

        // Do some class specific stuff
    }

}

class MyNetwork {

    // General case
    public void Add(SuperClass e) {
        Console.WriteLine("SuperClass call");
    }

    // Special case for some classes
    public void Add(SubClass e) {
        Console.WriteLine("SubClass call");

        // Do some class specific stuff
    }

}

which produces the output:

SuperClass call
SubClass call

I want to avoid having to copy and paste the code in ‘SuperClass’ about 20-30 times into each sub-class so that ‘this’ gets passed with the correct type (in my project it’s more than 1 line). I found the answer using ‘dynamic’, but as you might know unity’s compiler can’t use ‘dynamic’. I was wondering if there were any other methods to achieve the same result?

UPDATE:
I tried to replicate the IL. But it uses the namespace ‘Microsoft.CSharp.RuntimeBinder’ which I can’t access from my unity project.

Your example code seems just to be wrong in any OOP sense.

An abstract class is responsible for things that belongs to the generic case of the class. Your abstract class depends on the “MyNetwork” class directly and your “MyNetwork” class depends directly on your “SubClass” class. That makes the abstract class depend directly on SubClass as well. That would make the abstract class completely useless. You have way to much tight coupling and created a circular dependency between those classes.

You also should rethink about the responsibility of each class and what they actually represent. Why does the MyNetwork class need to know what kind of “SuperClass” instance you pass to it? Any SubClass specific code should be inside the SubClass. It seems you turned your MyNetwork class into a God Object.

Since you just posted an abstract example we can’t suggest which approach would be better since we can’t make much sense out of those class / method names.

Apparently we reached the maximum comment depth, so I’m posting here instead.

To avoid the circular dependency you could use something along the lines of the mediator pattern. Here’s an example of a possible strategy, with a loose interpretation of a mediator that ties everything together.

// NetworkManager service dependency
public interface INetworkManager
{
    void AddToNetwork(INetworkBlock block);
}

// Base block interface
public interface IBlock
{
    void Initialize();
}

// Abstract base class
public abstract class BlockBase: IBlock
{
    public virtual void Initialize() { }
}

// NetworkBlock interface & implementation
public interface INetworkBlock
{
    string NetworkId { get; set; }
}

public class NetworkBlock: BlockBase, INetworkBlock
{
    public string NetworkId { get; set; }
}

// Block repository interface & implementation
public interface IBlockRepository
{
    void AddBlock(IBlock block);
}

public class BlockRepository: IBlockRepository
{
    public void AddBlock(IBlock block) { /* add to internal collection */ }
}

// this is one possible way to tell the factory which block to create, but you could simply use different methods for each type instead
public enum BlockType { Unknown =0, Standard, Network, etc }

// Block factory/builder
public interface IBlockFactory
{
    IBlock CreateBlock(BlockType type);
}

public class BlockFactory: IBlockFactory
{
    public IBlock CreateBlock(BlockType type) { /* create the appropriate block */ }
}

// The BlockManager acts as a mediator
public interface IBlockManager
{
    void GenerateBlock(BlockType type);
}

public class BlockManager
{
    // these would be injected through IoC
    private readonly IBlockFactory _blockFactory;
    private readonly IBlockRepository _blockRepository;
    private readonly INetworkManager _networkManager;

    public void GenerateBlock(BlockType type)
    {
        // grab a block from the factory
        var block = _blockFactory.CreateBlock(type);

        // add to repository
        _blockRepository.AddBlock(block);

        // call init method
        block.Initialize();

        // for network block, also call the network manager
        if (block is INetworkBlock)
            _networkManager.AddToNetwork(block as INetworkBlock);
    }
}

This is just one possible solution, but in this you can see that now things are much more loosely coupled that what you had. The blocks no longer depend on the network service, the repository no longer performs business layer logic, and so forth.