Проблема довольно смутно определена, но, насколько я понимаю, у вас есть несколько возможностей
сначала используйте определение общего метода
public void Detele<T>(T toDelete); //optional : where T
и определите его в общем интерфейсе (или абстрактном классе, если это ваш случай)
В противном случае очень старая, но все еще надежная техника - перегрузка метода. Вы можете определить несколько методов с одним и тем же именем, но с разными аргументами. .Net активно использует этот шаблон в таких классах, как StreamReader, ToString и т. Д.
Из предоставленных вами подписей похоже, что вы можете найти для этого применение.
Третий вариант (хотя и более сложный для кодирования) - использование лямбда-выражений.
Add<T,P>(Action<T,P> addingAction, T source, P param) ( addingAction(source,param); );
//this is naive p.Add(q) it can be arbitralily more complicated
aObject.Add( (p,q) => p.Add(q), myObj, myParam);
Таким образом Вы определяете общее действие по добавлению, которое затем может быть инкапсулировано в Ваши объекты. Подпись, которую я предоставил, может быть легко изменена. Также Вы можете не захотеть выполнить действие сразу, а запланировать его для отложенного выполнения или выполнить асинхронно. Возможности с лямбда-выражениями бесконечны.
Также я предоставил реализацию, которая использует делегат Action. Вы можете легко преобразовать этот код в класс Expression, с помощью которого вы можете создавать свои собственные делегаты во время выполнения кода (и кэшировать их после инициализации, поскольку это довольно медленный процесс, т. Е. Отражение и прочее). Я настоятельно рекомендую злоупотреблять делегатами и выражениями. когда это возможно.
Береги себя
Лукаш