简体   繁体   中英

Storing a generic class and calling an overridden method in its non-generic derived class

Yeah. Talk about confusing titles. So this is the scenario: I've a generic class PromiseListener which looks like this:

public class PromiseListener<T>
{
    public virtual void IsResovled(T value)
    {
        return;
    }

    public virtual void IsSpoiled()
    {
        return;
    }
}

This class is supposed to be implemented and its methods overridden. An implementation of this class may look like this:

public class TestPromiseListener : PromiseListener<float>
{
    public override void IsResovled(float value)
    {
        System.Diagnostics.Debug.WriteLine("RMI RETURNED VALUE " + value);
    }
}

This TestPromiseListener is what's implemented by users. What I need to do is store listeners in a dictionary (key is irrelevant for this problem). This is the context of the problem: a promise is an unresolved return-value of a remote method which may eventually resolve to an actual value. A promise is immediately returned when a remote method invocation is made. So then you can "install" a PromiseListener whose methods have been implemented by a derived class ( TestPromiseListener ). One of these methods is IsResovled which takes one argument: the return value of the remote method invocation. This method would be called when the remote method invocation finally returns a value.

I'm having trouble storing the objects in a dictionary. I could store the listeners as object , but I don't see how I could get a listener from the dictionary without knowing the type first, because I would need to know its original type to cast it to. When fetching the PromiseListener I only know the type of the return value (and all information to fetch the right listener from a dictionary). So what I'm asking is: is there a type-safe way to store these generic objects, fetch them and call their methods?

(Some more detailed info as requested - sorry for the wall of text) Both IsResolved and IsSpoiled may be called at different times. A promise can resolve if a return value has been received (calls IsResolved ) or it may be spoiled when no return value could be received (due to a network error, for example) (calls IsSpoiled ). The PromiseListener a user implements may choose to override any of these methods. So internally I have a method which is called when a return value has been received from the network. In this method I have the identifier for the listener (key in the mentioned dictionary), the actual return value (object) and the AssemblyQualifiedName of the return value (which I can use to convert the return value of type object to the correct type). I'll then have to find the correct listener - which I can because I have its identifier - but I don't know how to fetch it in a type-save way because I don't know what type the listener is supposed to be.

?Type? listener; // Don't know what type the listener is. Could be PromiseListener<string> or PromiseListener<int> - or anything, really
if(promiseManager.TryGetPromiseListener(promise, out listener)
...

Is there some reason why you can't use a non -generic base class?

public abstract class PromiseListenerBase
{
    public abstract Type PromisedType { get; }
    public abstract void HandleResolution(object value);
}

public class PromiseListener<T> : PromiseListenerBase
{
    public override Type PromisedType
    {
        get { return typeof(T); }
    }
    public override void HandleResolution(object value)
    {
        T val = (T)value;
        this.IsResolved(val);
    }

    public virtual void IsResolved(T value) { /* some logic */ }
    public virtual void IsSpoiled() { /* some logic */ }
}

public class FloatListener : PromiseListener<float>
{
    public override void IsResolved(float value)
    {
        Console.Out.WriteLine("FloatListener value {0}", value);
    }
}

public class IntListener : PromiseListener<int>
{
    public override void IsResolved(int value)
    {
        Console.Out.WriteLine("IntListener value {0}", value);
    }
}

public class SomethingUsingPromiseListeners
{
    public void SomeMethod()
    {
        Dictionary<string, PromiseListenerBase> listeners =
            new Dictionary<string, PromiseListenerBase>();
        listeners.Add("float", new FloatListener());
        listeners.Add("int", new IntListener());
        int someValue = 123;
        foreach (PromiseListenerBase listener in listeners.Values)
        {
            if (listener.PromisedType == someValue.GetType())
            {
                listener.HandleResolution(someValue);
            }
        }
    }
}

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