using System.Collections.Generic;
public interface IGameActionAcceptor<T> {
void Accept(T gameAction);
public interface IGameAction<TGameActionAcceptor> {
void Visit(TGameActionAcceptor acceptor);
public class BaseGameAction<TInheritingGameAction, TAcceptor> : IGameAction<TAcceptor> where TAcceptor : IGameActionAcceptor<TInheritingGameAction> {
private TInheritingGameAction _inheritingGameAction;
public void Init(TInheritingGameAction inheritingGameAction) {
_inheritingGameAction = inheritingGameAction;
public void Visit(TAcceptor acceptor) {
acceptor.Accept(_inheritingGameAction);
public class ActionExecutor<TBaseGameActionAcceptor, TConcreteGameActionAcceptor> where TConcreteGameActionAcceptor: class where TBaseGameActionAcceptor: class {
private List<TBaseGameActionAcceptor> _acceptors = new List<TBaseGameActionAcceptor>();
public void Subscribe(TBaseGameActionAcceptor acceptor) {
_acceptors.Add(acceptor);
public void Execute(IGameAction<TBaseGameActionAcceptor> gameAction) {
foreach(var acceptor in _acceptors) {
gameAction.Visit(acceptor);
public void Execute(IGameAction<TConcreteGameActionAcceptor> gameAction) {
foreach(var acceptor in _acceptors) {
if (acceptor is TConcreteGameActionAcceptor)
gameAction.Visit(acceptor as TConcreteGameActionAcceptor);
public class BaseAction1 : BaseGameAction<BaseAction1, ABaseGameActionAcceptor> {
public class BaseAction2 : BaseGameAction<BaseAction2, ABaseGameActionAcceptor> {
public interface ABaseGameActionAcceptor :
IGameActionAcceptor<BaseAction1>,
IGameActionAcceptor<BaseAction2>
public interface AGameActionAcceptor :
IGameActionAcceptor<Action1>,
IGameActionAcceptor<Action2>
public class Action1 : BaseGameAction<Action1, AGameActionAcceptor> {
public class Action2 : BaseGameAction<Action2, AGameActionAcceptor> {
public class LoggingGameActionAcceptor : AGameActionAcceptor {
public void Accept(Action1 gameAction) {
System.Console.WriteLine("Action1");
public void Accept(Action2 gameAction) {
System.Console.WriteLine("Action2");
public void Accept(BaseAction1 gameAction) {
System.Console.WriteLine("BaseAction1");
public void Accept(BaseAction2 gameAction) {
System.Console.WriteLine("BaseAction2");
public static void Main() {
var executor = new ActionExecutor<ABaseGameActionAcceptor, AGameActionAcceptor>();
executor.Subscribe(new LoggingGameActionAcceptor());
executor.Execute(new Action1());
executor.Execute(new Action2());
executor.Execute(new BaseAction1());