Я использовал стратегию, которую вы упомянули в паре фреймворков, которые я с успехом построил. Одним из таких примеров является предоставление метаданных для инфраструктуры подключаемого модуля:
[AttributeUsage(AttributeTargets.Class, AllowMultiple=false, Inherited=false)]
public class PluginAttribute : Attribute
{
public string DisplayName { get; set; }
public string Description { get; set; }
public string Version { get; set; }
}
public interface IPlug
{
void Run(IWork work);
}
[Plugin(DisplayName="Sample Plugin", Description="Some Sample Plugin")]
public class SamplePlug : IPlug
{
public void Run(IWork work) { ... }
}
Это позволяет мне получать информацию о плагинах без необходимости их создания и чтения свойств метаданных.
По моему опыту, единственный способ обеспечить соблюдение обоих требований - выполнить проверки во время выполнения и убедиться, что жирный и мигающий в документация. Это далеко не оптимально, но это лучшее, что можно сделать (что я нашел). С другой стороны, я уверен, что есть лучший способ справиться с этим, но до сих пор это было довольно солидно для меня.