2009-04-12 3 views
4

Я пытаюсь собрать систему плагинов с .NET, и я не уверен, правильно ли я делаю это. Основой системы является то, что определенный каталог ({apppath}/Plugins /) будет иметь кучу предварительно скомпилированных библиотек DLL, и я хочу просмотреть каждый из них с отражением и для каждого доступного класса, если он наследует определенный базовый класс (это определено в еще одной DLL, но я расскажу об этом позже), затем создайте экземпляр и вызовите определенную функцию в указанном экземпляре.Createinstance() - Правильно ли я делаю это?

Public Sub ScanPluginsInDirectory(ByVal Directory As String) 

    Dim Plugins As New IO.DirectoryInfo(Directory) 
    Dim Files As IO.FileInfo() = Plugins.GetFiles("*.dll") 
    Dim CryptType As Type = GetType(CryptPluginBase) 
    Dim PluginsData as List(Of LoadedPluginsInfo) 

    For Each DllFile As IO.FileInfo In Files 
     Try 
      Dim thisAsm As Assembly = Assembly.LoadFrom(DllFile.FullName) 
      Dim ClassDefs = thisAsm.GetTypes().Where(Function(type) CryptType.IsAssignableFrom(type)) 

      For Each ClassDef As Type In ClassDefs 
       Dim A As Object 
       A = ClassDef.Assembly.CreateInstance(ClassDef.Name) 
       PluginsData.Add(New LoadedPluginsInfo(A.Plugin(), False)) 
      Next 
     Catch ex As Exception 
      Continue For 
     End Try 
    Next 
End Sub 

У меня есть конкретная проблема, я не уверен, что это правильный способ сделать это. Будет ли метод, который я пытаюсь выполнить, если можно предположить, что A.Plugin() фактически существует, и любые структуры и классы, на которые делается ссылка здесь, являются ошибками? Если кому-то понадобится больше кода, чтобы помочь, я могу опубликовать его.

ответ

3

В целом стратегия должна работать. Вызов Assembly.LoadFrom загрузит целевую сборку в процесс. Оттуда можно провести проверку типов и создать экземпляры этих типов.

Я думаю, что самый простой и надежный способ создания экземпляра - использовать метод Activator.CreateInstance.

For Each def As Type in ClassDefs 
    Dim inst = Activator.CreateInstance(def) 
    PluginsData.Add(new LoadedPluginsInfo(inst.Plugin(), False)) 
Next 

В зависимости от ваших целей, еще одно предложение было бы переместить блок Try/Поймать в петлю вместо из него. Наличие блока Try/Catch на внешней стороне цикла означает, что если какой-либо заданный тип сборки имеет ошибку, вы отбросите все типы из этой сборки. Перемещение внутри него позволит вам отбросить только те типы, которые не работают как expect.d Однако текущее поведение может быть вашим намерением.

+0

Вы имеете в виду inst.Plugin()? – Sukasa

+0

@ Сукаса, да. Я исправил это. – JaredPar

+1

Хорошо, я не был уверен, был ли небольшой трюк, о котором я не знал. Благодаря! – Sukasa

1

Это должно сработать, я использовал такие вещи в некоторых проектах раньше. Я специально искал конструктора и вызывал его, но кроме того, это была та же идея.

Но вы можете посмотреть на MEF, который позаботится о вас для архитектуры плагинов (если вы готовы немного подождать для версии выпуска, она по-прежнему остается CTP).

Смежные вопросы