Вы уже почти все знаете, чтобы судить о том, какой подход лучше.
Как уже упоминалось, у вас не может быть статических интерфейсов, определенных для вашего типа, поэтому вы не можете гарантировать, что новый разработчик принудительно добавил для добавления атрибута.
Итак, две выбранные вами альтернативы - единственные две, о которых я могу подумать.Теперь давайте сделаем плюсы и минусы и попытаемся отточить их.
Атрибут
Вы можете уменьшить боль, гарантируя, что разработчики помещают атрибуты в классы с осмысленными сообщениями об ошибках.Я бы сказал, что вы должны управлять обнаружением классов, основанных исключительно на Атрибутах, а не на наследовании.Если вы управляете всем с помощью атрибутов, вам не нужно наследовать от виджета.Это профессионал, потому что теперь каждый может наследовать, если это желательно, и повторно внедрять, если это предпочтительно.
Дело в том, что реализация обнаруживаемости будет более сложной: вам нужно будет использовать отражение при запускеполучите MethodInfo
, убедитесь, что метод имеет правильную сигнатуру, дайте правильные ошибки в случае, и при необходимости вызовите метод, распаковывая результат.
Подумайте об этом: вам нужен статический метод, потому что вы не используетене нужно создавать экземпляр одного типизированного экземпляра Widget, но на самом деле создание нового Widget вполне может быть не таким уж большим делом., что может быть в порядке, необходимо или совершенно необязательно (судите сами), но вы получаете самодокументируемый опыт.
Очевидным доводом является то, что при запуске вам нужно создать экземпляр виджета для каждого обнаруженного вами производного типа, ноэто вполне может быть арахис по сравнению со сборкой сканирования и проверки типа и методаОбнаружение информации и вызовы методов через рефлексию.Гадкий?Вид.Неэффективное?Не так много.И это код, который невидим для вашего конечного пользователя.
ИМХО
Я нахожу весьма неплохой компромисс при разработке фреймворка, чтобы поместить некоторый "уродливый" код внутрь фреймворк, если это означает, что каждая реализация, использующая библиотеку, будет даже немного лучше.
В общем, если вы разрабатываете библиотеку, которую вы хотите быть гибкой и доступной для обнаружения, выследует ожидать, что разработчик прочитает хотя бы краткое руководство по началу работы.Если они смогут прочитать за 5 минут один бит информации («расширить базовый класс» или «добавить один или несколько атрибутов»), и этот единственный бит даст им направление для обнаружения каждого аспекта регистрации виджета, я был быхорошо: вы не можете стать намного лучше, чем это.
Мой звонок: я бы пошел по пути абстрактного класса с небольшим предостережением.Мне действительно не нравится иметь обязательный базовый класс.Поэтому я бы организовал обнаружение при запуске на основе интерфейса IWidget
, содержащего метод GetOptionsSchema
и все необходимое для использования виджета (который может быть методом DoStuff
, но вполне может быть чем-то другим).При запуске вы ищете реализации интерфейса, которые не являются абстрактными, и вы готовы пойти.
Если , и только если, единственный бит, который вы действительно Заранее нужна строка или другой аналогичный простой тип, мне потребуется дополнительный атрибут.
[OptionsSchemaName("http://something")]
public class MyWidget : WidgetBase
{
public overide DoStuff(Options options)
{
//Do some FooWidget stuff
}
public static OptionSchema GetOptionsSchema()
{
//Return options for FooWidget
}
}
Затем ваша инфраструктура обнаружения типов может искать неабстрактные IWidget
s и выдавать значимую ошибку.прямо при запуске как the type MyWidget is lacking an OptionsSchemaName attribute. Every implementation of IWidget must define one. See http://mydocs for information
.
Bang!Пригвоздил это!