Паттерн возникает, когда несколько человек (или команд) приходят к одинаковым или идентичным решениям. Многие люди до сих пор используют синглтоны в их оригинальном виде или с помощью заводских шаблонов (хорошее обсуждение в Modern C ++ Design Александреску). Параллельность и сложность в управлении временем жизни объекта являются главными препятствиями, а первые легко управляются, как вы предлагаете.
Как и все варианты, у Синглтона есть свои плюсы и минусы. Я думаю, что они могут быть использованы в модерации, особенно для объектов, которые выживают в течение срока службы приложения. Тот факт, что они похожи (и, вероятно, являются) глобалами, предположительно вызвал пуристов.
Чтобы реализовать интерфейс плагина вручную, вам понадобится метод, подобный этому. Я оставил несколько TODO, в которых вы хотели бы улучшить обработку ошибок и / или сделать реализацию немного более конкретной.
public List<T> LoadPlugin<T>(string directory)
{
Type interfaceType = typeof(T);
List<T> implementations = new List<T>();
//TODO: perform checks to ensure type is valid
foreach (var file in System.IO.Directory.GetFiles(directory))
{
//TODO: add proper file handling here and limit files to check
//try/catch added in place of ensure files are not .dll
try
{
foreach (var type in System.Reflection.Assembly.LoadFile(file).GetTypes())
{
if (interfaceType.IsAssignableFrom(type) && interfaceType != type)
{
//found class that implements interface
//TODO: perform additional checks to ensure any
//requirements not specified in interface
//ex: ensure type is a class, check for default constructor, etc
T instance = (T)Activator.CreateInstance(type);
implementations.Add(instance);
}
}
}
catch { }
}
return implementations;
}
Пример вызова:
List<IPlugin> plugins = LoadPlugin<IPlugin>(path);
Что касается части вашего вопроса о C ++. Есть несколько разных подходов к этому, хотя правильный выбор зависит от вашей конкретной ситуации. Вы можете создать clr-совместимую .dll в C ++, на которую ваш проект C # может ссылаться и вызывать как любую другую .dll, на которую он ссылается. Кроме того, вы можете использовать P / Invoke для вызова собственной .dll.
Одной из самых простых концепций подключаемых модулей, которые я когда-либо использовал, была, безусловно, Managed Extensibility Framework , которая будет частью .NET 4 (afaik). К сожалению, он еще не закончен, и доступен только предварительный просмотр, который может отличаться от окончательной версии. При этом мы использовали MEF Preview 3 для uni-проекта, и он работал без проблем и, безусловно, значительно упростил работу с плагинами.
Посмотрите на пространство имен System.Addin : http://msdn.microsoft.com/en-us/library/system.addin.aspx
В противном случае вы можете все сделать самостоятельно. До того, как это пространство имен стало доступным, я использовал общий интерфейс «IPlugin», который должен был использовать каждый плагин / надстройка. Затем у меня был загрузчик, который проверял все * .dll в папке, а затем использовал отражение для проверки интерфейса. Затем я мог бы создать экземпляры классов, которые реализуют мой интерфейс плагинов / дополнений
. Файлы cpp, вероятно, потребуется преобразовать в C #, или вы могли бы создать dll для ссылки.
.NET Framework внутренне использует модель COM. См. http://blog.caljacobson.com/2007/07/26/creating-a-plug-in-framework-in-c-resources/ для получения списка примеров подключаемых модулей, использующих этот метод.