Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Invoking generic method/delegate from a non-generic base class

Tags:

c#

generics

I have the feeling I'm not looking at this issue from the right angle here, and I'm just not thinking of other solution.

Assuming this generic class;

public abstract class Port<T>
{
    public delegate T PullDelegate();

    private PullDelegate pull;

    public Port(PullDelegate pull)
    {
        this.pull = pull;
    }

    public T Pull()
    {
        return pull();
    }
}

It is used to define "ports" in a graph-node editor. A port can transfer a object/value from one node to another, but they also need to be "type-safe", which means I cannot plug any port to another of the wrong type (at least not without some conversion).

The node "owns" a port and give it a delegate towards one of its method so when another node "pull" on a value, the port simply invokes it and returns the proper value.

My issue starts when I'm trying to call Pull() from a non-generic collection. Obviously, I could make a non-generic base method, but then Pull could not return T, it would need to return object.

Also, each nodes have collection accessors for their ports so the other items can get them. That collect has to be non-generic because a node can have many ports of many type.

    public abstract Port[] Inputs { get; }
    public abstract Port[] Outputs { get; }
    public abstract Port[] Entries { get; }
    public abstract Port[] Exits { get; }

The moment the non-generic type get into play, everything generic become inaccessible. If only Port<>[] would be a thing.

I'm feeling like I'm missing something...

like image 559
LightStriker Avatar asked Oct 18 '22 18:10

LightStriker


1 Answers

Make Port<T> implement the non-generic interface IPort using explicit implementations. In that way it's hidden from the API but still allow you to invoke methods in the generic classes.

public interface IPort
{
    object SomeAction(object data);
}

public class Port<T> : IPort
{
    //[.. all other methods ..]


    object IPort.SomeAction(object data)
    {
        var typedData = (T)data;
        //invoke our typed version.
        return SomeAction(data);
    }

    public T SomeAction(T data)
    {
         // ...
    }
}
like image 90
jgauffin Avatar answered Oct 21 '22 15:10

jgauffin