views:

139

answers:

2

This may seem a bit odd, but I really need to create a workaround for the very complicated duplex - communication - handling in C#, especially to force other developers to observe the DRY - principle.

So what I'm doing is to have a type based multiton that looks like this:

internal sealed class SessionManager<T> where T : DuplexServiceBase

which is no problem at all - so far.

However, as soon as I want to have the services (I'm going with one instance per session) register themselves with the SessionManager, the hassle starts:

internal abstract class DuplexServiceBase : MessageDispatcherBase<Action>

(MessageDispatcherBase being a class of mine that creates a thread and asynchronously sends messages).

I want to have a method that looks like this:

    protected void ProcessInboundMessage()
    {
        // Connect
        SessionManager<self>.Current.Connect(this);
    }

...but the problem is - how would I get to the "self"?

I really NEED separate session managers for each service class, because they all have their own notifications (basically it's the very annoying "NotifyAllClients" - method that makes we want to pull my own hair out for the last hours) and need to be treated separately.

Do you have ANY ideas?

I don't want to use "AsyncPattern = true", btw... this would require me to give up type safety, enforced contract compliance (this would lead to very bad abuse of the communication system I'm setting up here) and would require abandoning the DRY - principle, there would be a lot of repetitive code all over the place, and this is something I seriously frown upon.

Edit:

I have found the best possible solution, thanks to the answers here - it's an EXTENSION METHOD, hehe...

    public static SessionManager<T> GetSessionManager<T>(this T sessionObject) 
        where T : DuplexServiceBase
    {
        return SessionManager<T>.Current;
    }

I can use this like this:

GetSessionManager().Connect(this);

Mission accomplished. :-D

This method (belongs to DuplexServiceBase) gives me the session manager I want to work with. Perfect! :-)

+8  A: 

I'd write a helper method:

static class SessionManager { // non-generic!
    static void Connect<T>(T item) where T : DuplexServiceBase {
        SessionManager<T>.Current.Connect(item);
    }
}

and use SessionManager.Connect(this) which will figure it out automatically via generic type inference.

Marc Gravell
you are a genius, I would give you +100, if I could for THAT answer. Thank you sooooooo much!!
Turing Complete
Surely `SessionManager<T>.Current.Connect(item);`?
Tim Robinson
Hehe, I had to replace the "this" with "item", of course. :-)
Turing Complete
@Turing - ah yes; sorry - copy/paste. Fixed.
Marc Gravell
+3  A: 

You could wrap the call in a generic method, thereby taking advantage of the compiler's type inference:

private static void ConnectSessionManager<T>(T service)
{
     SessionManager<T>.Current.Connect(service)
}

protected void ProcessInboundMessage()
{
    // Connect
    ConnectSessionManager(this);
}
Tim Robinson