Все это отражение не будет быстрым. Обратите внимание, как отражение происходит при каждом столкновении. В этом проблема.
Некоторые мысли.
Мысль номер один: шаблон посетителя.
Стандартный способ реализовать достаточно быструю двойную виртуальную диспетчеризацию на языках ОО - это создать реализацию шаблона посетителя.
Можете ли вы реализовать шаблон посетителя, согласно которому каждый получатель в посетителе ведет список «действий, которые необходимо выполнить в этой ситуации»? Тогда ваш метод сумматора состоит из определения правильного места для написания новой «вещи, которую нужно сделать», и затем добавления делегата к этой вещи. Когда происходит столкновение, вы начинаете посетителя выполнять двойную диспетчеризацию, находите делегат действий и вызываете его.
Вам нужно больше, чем двойная отправка? Эффективная многократная виртуальная отправка выполнима, но это не совсем просто.
Мысль номер два: динамическая отправка
C # 4 имеет динамическую отправку. Как это работает, мы используем отражение при первом обнаружении сайта вызова для анализа сайта вызова. Затем мы динамически генерируем новый новый IL для выполнения вызова и кешируем IL. Во втором вызове мы размышляем над аргументами, чтобы увидеть, являются ли они точно такими же типами, как и раньше. Если они есть, мы повторно используем существующий IL и просто вызываем его. Если нет, мы делаем анализ снова. Если аргументы обычно бывают только нескольких типов, то кэш очень быстро начинает только попадать, а не пропускает, и производительность на самом деле довольно хорошая, учитывая все обстоятельства. Конечно, быстрее, чем много размышлений каждый раз. Единственное отражение, которое мы делаем каждый раз, - это анализ типа аргументов во время выполнения.
Мысль номер три: реализовать собственную динамическую диспетчеризацию
В том, что делает DLR, нет ничего волшебного. Один раз он анализирует, выплевывает немного IL и кеширует результат. Я подозреваю, что ваша боль случается, потому что вы каждый раз проводите повторный анализ.