Question on Generics

Suppose I have an event reactor pattern set up like this:


public interface IEventDispatcher
{
void Subscribe(IEvent newEvent, EventDispatcherHandler handler);
void FireEvent(IEvent newEvent);
}

public delegate void EventDispatcherHandler(IEvent newEvent);

public interface IEvent
{
// ... meaningful eventing stuff goes here ...
}

 

This is all well and good as it decouples senders and receivers, blah blah blah… And in the real code these are all in separate files and all that jazz.

Anyway, something I’ve noticed many times in doing event dispatcher patterns is a tendency for these “events” to become “commands” as well… so you might have the “SaveThing” class… but then you’ll add the “ThingSavingEvent” class (which is cancellable) and the “ThingSavedEvent” class. For every “command event” you’ll have the pre- and post-events as well.

And what do they teach us about code duplication? ( =

So here’s what I wanted to do:


public interface ICommand
{
// ... do command stuff here ...
}

public interface ICommandExecuter<t> where T : class, ICommand
{
void DoCommand(T command);
void UndoCommand(T command);
}

public class CommandRegistry
{
private IEventDispatcher dispatcher;

void RegisterExecuter</t><t>(ICommandExecuter</t><t> executer) where T : class, ICommand
{
 // register executer here
}

void Execute(ICommand command)
{
 // fire precommandevent for this command
 // iterate over each command executer instance for that command
 // fire postcommandevent for this command
}

}

// here's the part I'm pretty sure won't work...
public class PreCommandEvent</t><t> : IEvent where T : class, ICommand
{
}

public class PostCommandEvent</t><t> : IEvent where T : class, ICommand
{
}
</t>
 

Here’s how it works: the CommandRegistry gets a bunch of ICommandExecuter<> instances for different commands… the SaveCommand, the ExitCommand, and so on (eventually I want to put something in the CommandRegistry to maintain order, to make the command executers transactional… but I digress). Before the CommandRegistry iterates through the executers it constructs and fires a PreCommandEvent<> of the appropriate type. Here’s a concrete example.

1. Program needs to throw the SaveCommand which implements ICommand.
2. Program calls registry.Execute(new SaveCommand());
3. Registry constructs an instance of the type PreCommandEvent and fires it
4. Registry finds list of ICommandExecuter
and calls DoCommand() on each one
5. Registry constructs an instance of the type PostCommandEvent
and fires it

Steps 3 – 5 are the problem here. The language does not support doing things like this:


IEvent ev = new PostCommandEvent(typeof(command));

 

That just doesn’t make sense. Passing a Type object in isn’t syntactically correct there… the type name is what’s expected. And not a string, either.

So, yes, I know I can do some reflection to generate the an instance of the appropriate type… and it’s not that I think reflection is hard, or anything like that… but a lot of the reflection examples depend on the run-time type of an instance of a generic type looking like this: PostCommandEvent`1[[SaveCommand, ]] Isn’t that implementation specific? Wouldn’t that code have to create the type in a different way on Mono (assuming that the Mono programmers track closed generic types differently)?

Comments are closed.