Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Createinstance() - Am I doing this right?

I'm trying to put together a plugins system with .NET, and I'm not sure if I'm doing it correctly. The basis of the system is that a specific directory ({apppath}/Plugins/) will have a bunch of precompiled DLLs, and I want to look through each one with reflection, and for every class available, if it inherits a specific base class (this is defined in yet another DLL, but I'll go into that later), then create an instance of it and call a specific function in said instance.

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

The specific problem I have is, I'm not sure this is the right way to do this. Would the method I'm trying to do work, if it can be assumed that A.Plugin() actually exists and any structures and classes referenced here are bug-free? If anyone would need more code in order to help, I can post it.

like image 254
Sukasa Avatar asked Apr 12 '09 19:04

Sukasa


2 Answers

Overall the strategy should work. The Assembly.LoadFrom call will load the target assembly into the process. From there it is possible to do type inspection and create instances of those types.

I think the easiest and most reliable way to create the instance is to use the Activator.CreateInstance method.

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

Depending on your goals, another suggestion would be to move the Try/Catch block into the loop instead of out of it. Having the Try/Catch block on the outside of the loop means that if any given type in an assembly does have an error, you will discard all types from that assembly. Moving it inside will allow you to discard only the types that do not work as expect.d The current behavior may be your intent though.

like image 198
JaredPar Avatar answered Sep 24 '22 23:09

JaredPar


This should work, I've been using this kind of thing in some projects before. I specifically looked for a constructor and invoked it but apart from that it was the same idea.

But you might want to look at MEF, which takes care of a LOT of things for you for a plugin architecture (if you are willing to wait a bit for the release version, it's still CTP for now).

like image 35
Denis Troller Avatar answered Sep 21 '22 23:09

Denis Troller