Кажется, что на самом деле здесь есть несколько разных проблем, которые нужно решить. Основная проблема заключается в попытке создать механизм, позволяющий вставить произвольный объект в существующий список в некоторой точке в середине этого списка.
Вы не описываете, как на самом деле выглядит интерфейс IMetadataProvider, но у него должен быть какой-то способ уникальной идентификации провайдера (лучший вариант - использовать Guid). Преимущество по сравнению с использованием имени класса заключается в том, что оно позволяет вам переименовывать классы по мере необходимости во время рефакторинга и т. Д., Не затрагивая пользовательских (сторонних) поставщиков, если вы сохраняете Guid прежним.
Вместо того, чтобы использовать простой список, вы, вероятно, должны получить свой собственный список:
class ProviderList : List<IMetadataProvider { }
, который предоставляет возможность для собственного (стороннего) поставщика установить / удалить себя из этого списка. Эти механизмы должны быть достаточно умными, чтобы знать, как вставить нового провайдера в середину цепочки, и достаточно умными, чтобы знать, как обрабатывать несколько пользовательских провайдеров, которые были вставлены. Точно так же процесс удаления должен быть продуманным, чтобы справляться с подобными проблемами, а также гарантировать, что кто-то не попытается удалить одного из ваших «основных» провайдеров.
Хорошим подходом здесь, вероятно, будет передача Guid провайдера, после которого вы хотите вставить его, в качестве параметра метода Install (). Метод Remove () также использует Guid провайдера для удаления.
Например, допустим, я вставляю нового поставщика после MovieProviderFromXml. Затем другой сторонний поставщик также устанавливает нового поставщика после MovieProviderFromXml. Каким должен быть новый порядок цепочек? Всегда ли второй провайдер вставляет сразу после MovieProviderFromXml или запускает его там, а затем пропускает мимо любых пользовательских провайдеров и вставляет после последнего установленного нестандартного провайдера (то есть перед следующим «основным» провайдером?
С этим вопросом связана идея о том, что у вас должен быть какой-то способ различать ваших «основных» провайдеров и нестандартных провайдеров.
Наконец, вам нужно убедиться, что есть способ обработки сбоев в цепочке, особенно когда пользовательский провайдер вставлен в неправильное место.
Вы хотите всегда поддерживать базовый ("основной") список цепочки по умолчанию. Когда новый поставщик установлен в середине этой цепочки, новая цепочка должна быть создана, но вы не хотите терять базовую цепочку. Это дает вам возможность вернуть цепь в состояние по умолчанию.
Цепочка, основанная на приоритете, является проблематичной, поскольку вам необходимо определить, как обрабатывать приоритетные коллизии. Что касается набора атрибутов До / После, разрешите ли вы оба на одном и том же провайдере? Вероятно, нет, поэтому может иметь смысл создать атрибут ProviderChainAttribute со свойством перечисления ChainInsert, где ChainInsert определяет значения перечисления «До» и «После». Это позволяет принудить пользовательского поставщика принять решение о том, устанавливать ли он до или после указанного поставщика. Я бы все равно использовал Guid, а не тип.
Надеюсь, это даст вам другие идеи о том, как подойти к этой проблеме.