Createinstance () - я делаю это правильно? - PullRequest
5 голосов
/ 12 апреля 2009

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

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() действительно существует и любые структуры и классы, на которые есть ссылки, не имеют ошибок? Если кому-то понадобится больше кода, чтобы помочь, я могу опубликовать его.

Ответы [ 2 ]

3 голосов
/ 13 апреля 2009

В целом стратегия должна работать. Вызов 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 / Catch в цикл, а не из него. Наличие блока Try / Catch снаружи цикла означает, что если какой-либо конкретный тип в сборке имеет ошибку, вы отбрасываете все типы из этой сборки. Перемещение внутрь позволит вам отбросить только те типы, которые не работают должным образом. Хотя текущее поведение может быть вашим намерением.

1 голос
/ 13 апреля 2009

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

Но вы, возможно, захотите взглянуть на MEF , который позаботится о МНОЖЕСТВЕ за вас для архитектуры плагина (если вы готовы немного подождать релизную версию, это все еще CTP в настоящее время).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...