Results 1 to 12 of 12

Thread: [RESOLVED] [2005] My "plan" for dynamic add-on component loading - Thoughts?

  1. #1

    Thread Starter
    Junior Member
    Join Date
    Jul 2007
    Location
    Bergen, Norway
    Posts
    31

    Resolved [RESOLVED] [2005] My "plan" for dynamic add-on component loading - Thoughts?

    Hi!

    I am currently developing an application that will be the "base" for several components (business reporting systems, order management, etc). The idea is that our customers will install this "mother application", and we will offer components that will slot into it, expanding the functionality.

    Now, here's my idea for how to make this work. I have some of this basic functionality down, but I want to get other people's opinions, ideas and experiences with this sort of thing before I move too far in a direction that might not be the best way to go:

    - The components have an "interface" that is inherited from a base class that both the mother application and the component knows about. This will be their means of communicating with eachother

    - The components are compiled into DLLs. The mother application goes through these DLLs and looks for an implementation of the base interface:

    Here is the "complete" Sub for loading the components
    Code:
      Public LoadedModules As New ModuleCollection 
    
      Private Sub LoadModules()
        Try
          ' Information installed modules is stored in a database table.
          ' Retrieve it and go through the data rows to load each module
          Dim dtModules As New SystemDataset.BUS_InstalledModulesDataTable
          g_taInstalledModules.Fill(dtModules)
    
          ' Clear the module collection
          LoadedModules.Clear()
    
          For Each rw As SystemDataset.BUS_InstalledModulesRow In dtModules.Rows
    
            ' The module directory name.
            ' MODULES_FOLDER is just a string constant containing the
            ' application path subfolder name where the modules reside
            Dim dirInfo As New System.IO.DirectoryInfo(Application.StartupPath & "\" & MODULES_FOLDER & "\" & rw.ModuleFolder)
    
            Try
              ' Just check some folder rights and stuff
              If CheckFolderRights(dirInfo.FullName) <> FolderRight.Full Then
                Throw New Exception("Insufficient access to module folder '" & _
                rw.ModuleFolder & "' (need full read/write access)! " & _
                "Aborting module load for module '" & rw.Name & "'.")
              End If
    
              ' Create an assembly object and try to load the
              ' assembly name from the datarow (e.g. "ComponentName")
              Dim asm As Reflection.Assembly
              asm = Reflection.Assembly.LoadFrom(dirInfo.FullName & "\" & rw.ModuleAssembly)
    
              ' Try to create an instance of the common interface,
              ' so that the mother application will have an object to
              ' communicate with the component through
              Dim mdl As BaseModule
              mdl = asm.CreateInstance(rw.ModuleNamespace & "." & rw.ModuleInterface)
              mdl.ModuleId = rw.Module_ID
    
              ' Add the newly loaded component to the collection
              LoadedModules.Add(mdl)
    
            Catch ex As Exception
              ExceptionHandler(ex)
            End Try
          Next
    
        Catch ex As Exception
          ExceptionHandler(ex)
        End Try
      End Sub
    The important bit is really this, which deals with the creating and loading of a named assembly:
    Code:
              ' Create an assembly object and try to load the
              ' assembly name from the datarow (e.g. "ComponentName")
              Dim asm As Reflection.Assembly
              asm = Reflection.Assembly.LoadFrom(dirInfo.FullName & "\" & rw.ModuleAssembly)
    
              ' Try to create an instance of the common interface,
              ' so that the mother application will have an object to
              ' communicate with the component through
              Dim mdl As BaseModule
              mdl = asm.CreateInstance(rw.ModuleNamespace & "." & rw.ModuleInterface)
              mdl.ModuleId = rw.Module_ID
    ModuleCollection is simply a class that extends CollectionBase:
    Code:
    Public Class ModuleCollection
      Inherits System.Collections.CollectionBase
    
      Public Sub Add(ByVal Mdl As BaseModule)
        ' Invokes Add method of the List object to add a widget.
        List.Add(Mdl)
      End Sub
    
      Public Sub Remove(ByVal index As Integer)
        If index > Count - 1 Or index < 0 Then
          Throw New Exception("Error removing item! No module at index " & index & "!")
        Else
          List.RemoveAt(index)
        End If
      End Sub
    
      Public ReadOnly Property Item(ByVal index As Integer) As BaseModule
        Get
          Return CType(List.Item(index), BaseModule)
        End Get
      End Property
    End Class
    (I'm aware that referring to the components as "Modules" might make the code a bit hard to read, and I've since realised the error of my ways. This will be rewritten )


    Hopefully this post makes some sense. Basically, The mother application needs to dynamically load "add-on" components that are not compiled into or together with the actual application (ie: The mother application has absolutely zero knowledge about the component at compile-time). We need to be able to add a DLL to the application at any time, and have the mother application be able to use it to load MDI child forms, menus, toolstrips and generally use it to expand its own functionality. Am I on the right path here, or is there some other way I should look at?

  2. #2
    PowerPoster Jenner's Avatar
    Join Date
    Jan 2008
    Location
    Mentor, OH
    Posts
    3,712

    Re: [2005] My "plan" for dynamic add-on component loading - Thoughts?

    No, it sounds like you're on a pretty good path. You may want to define some Interface objects for your component objects to implement as well since that's their definition. For example, if you have some common parameter elements in your MDI forms, you could define an IMyMdiForm interface declaration, then all MDI forms you use would implement it, even in the external components. Interfaces make things easier in the exact situation you're describing since you don't have to declare specific classes as long as it implements the proper interface.
    My CodeBank Submissions: TETRIS using VB.NET2010 and XNA4.0, Strong Encryption Class, Hardware ID Information Class, Generic .NET Data Provider Class, Lambda Function Example, Lat/Long to UTM Conversion Class, Audio Class using BASS.DLL

    Remember to RATE the people who helped you and mark your forum RESOLVED when you're done!

    "Two things are infinite: the universe and human stupidity; and I'm not sure about the universe. "
    - Albert Einstein

  3. #3

    Thread Starter
    Junior Member
    Join Date
    Jul 2007
    Location
    Bergen, Norway
    Posts
    31

    Re: [2005] My "plan" for dynamic add-on component loading - Thoughts?

    Yup, I've got a "base" form (and quite a few other base controls) that my components use, so I've got that covered. I'm a total inheritance *****

  4. #4
    PowerPoster Jenner's Avatar
    Join Date
    Jan 2008
    Location
    Mentor, OH
    Posts
    3,712

    Re: [2005] My "plan" for dynamic add-on component loading - Thoughts?

    Sounds like you're all set then. The hard part will be making sure everything is segregated into their appropriate project and that there's no spots in the application that'll have a heart-attack if one of those DLL files is missing.
    My CodeBank Submissions: TETRIS using VB.NET2010 and XNA4.0, Strong Encryption Class, Hardware ID Information Class, Generic .NET Data Provider Class, Lambda Function Example, Lat/Long to UTM Conversion Class, Audio Class using BASS.DLL

    Remember to RATE the people who helped you and mark your forum RESOLVED when you're done!

    "Two things are infinite: the universe and human stupidity; and I'm not sure about the universe. "
    - Albert Einstein

  5. #5

    Thread Starter
    Junior Member
    Join Date
    Jul 2007
    Location
    Bergen, Norway
    Posts
    31

    Re: [2005] My "plan" for dynamic add-on component loading - Thoughts?

    The biggest hurdle I may come across is if we install one component, and then in the course of developing the system(s) further, we have to update the base interface, essentially creating a completely new version of the DLL.

    I'm hoping that as long as I keep the function signatures intact, I can mess with the code and internal variables. The only thing I worry about is the application detecting DLL version conflicts. Could this be an issue? If so, is there something I should think about to avoid such problems?

  6. #6
    PowerPoster Jenner's Avatar
    Join Date
    Jan 2008
    Location
    Mentor, OH
    Posts
    3,712

    Re: [2005] My "plan" for dynamic add-on component loading - Thoughts?

    Just make sure you have the DLLs marked as "Use any version". I'd use Interfaces as well. You have all your subcomponents implement a common interface with the main program. Since you can implement multiple interfaces, if your main program changes to the point where you need extra common functionality from the subcomponents, you build a second Interface object and implement that as well in all your new subcomponents.

    A quick check of the Interface models they support will show your main program what versions of the subcomponents it has available and what modes of operation they support.

    Also, if this is a commercial program, you should have a license scheme that takes into account your module options. This way, when they install the program, they can enter the license and it'll install/update the DLL files it needs, so hopefully, you never run into a mix-matched condition.
    My CodeBank Submissions: TETRIS using VB.NET2010 and XNA4.0, Strong Encryption Class, Hardware ID Information Class, Generic .NET Data Provider Class, Lambda Function Example, Lat/Long to UTM Conversion Class, Audio Class using BASS.DLL

    Remember to RATE the people who helped you and mark your forum RESOLVED when you're done!

    "Two things are infinite: the universe and human stupidity; and I'm not sure about the universe. "
    - Albert Einstein

  7. #7

    Thread Starter
    Junior Member
    Join Date
    Jul 2007
    Location
    Bergen, Norway
    Posts
    31

    Thumbs up Re: [2005] My "plan" for dynamic add-on component loading - Thoughts?

    Quote Originally Posted by Jenner View Post
    Since you can implement multiple interfaces, if your main program changes to the point where you need extra common functionality from the subcomponents, you build a second Interface object and implement that as well in all your new subcomponents.
    That's an excellent idea, I didn't think of that.

    Do you know if there is a way for the mother application to ask what interfaces the component implements, or do I have to look for function signatures?

    Quote Originally Posted by Jenner View Post
    A quick check of the Interface models they support will show your main program what versions of the subcomponents it has available and what modes of operation they support.
    Yeah, I'm going through a few different options to make the mother application be able to determine what functionality is and isn't present in any given component. Hopefully I'll be able to do this with some kind of automated check for function signatures and such, and avoid having to base this on a version number that I have to maintain (because... well, I suck at versioning)

    Quote Originally Posted by Jenner View Post
    Also, if this is a commercial program, you should have a license scheme that takes into account your module options. This way, when they install the program, they can enter the license and it'll install/update the DLL files it needs, so hopefully, you never run into a mix-matched condition.
    Yes, in an ideal world, that'd be the plan, but we're always releasing updates, and customers frequently want other components at a later date, or they want functionality that isn't offered in the "base model", so we'll write special versions for them. Of course, this special version should not have to mess with the interface, so hopefully we'll be able to dodge that bullet.
    Last edited by Naigewron; Mar 17th, 2009 at 09:55 AM.

  8. #8
    PowerPoster Jenner's Avatar
    Join Date
    Jan 2008
    Location
    Mentor, OH
    Posts
    3,712

    Re: [2005] My "plan" for dynamic add-on component loading - Thoughts?

    Quote Originally Posted by Naigewron View Post
    Yes, in an ideal world, that'd be the plan, but we're always releasing updates, and customers frequently want other components at a later date, or they want functionality that isn't offered in the "base model", so we'll write special versions for them. Of course, this special version should not have to mess with the interface, so hopefully we'll be able to dodge that bullet.
    Yea, we're in the same boat with software design. Customers wanting everything their own way. With enough swappable components though, you can make almost anything possible.
    My CodeBank Submissions: TETRIS using VB.NET2010 and XNA4.0, Strong Encryption Class, Hardware ID Information Class, Generic .NET Data Provider Class, Lambda Function Example, Lat/Long to UTM Conversion Class, Audio Class using BASS.DLL

    Remember to RATE the people who helped you and mark your forum RESOLVED when you're done!

    "Two things are infinite: the universe and human stupidity; and I'm not sure about the universe. "
    - Albert Einstein

  9. #9
    PowerPoster techgnome's Avatar
    Join Date
    May 2002
    Posts
    34,687

    Re: [2005] My "plan" for dynamic add-on component loading - Thoughts?

    Something else you could do with the versioning is to implement a version interface, then the app could query the component's version interface to see what version it implements. Then based on that you would know what interface to expect from the component.

    -tg
    * I don't respond to private (PM) requests for help. It's not conducive to the general learning of others.*
    * I also don't respond to friend requests. Save a few bits and don't bother. I'll just end up rejecting anyways.*
    * How to get EFFECTIVE help: The Hitchhiker's Guide to Getting Help at VBF - Removing eels from your hovercraft *
    * How to Use Parameters * Create Disconnected ADO Recordset Clones * Set your VB6 ActiveX Compatibility * Get rid of those pesky VB Line Numbers * I swear I saved my data, where'd it run off to??? *

  10. #10
    Frenzied Member ntg's Avatar
    Join Date
    Sep 2004
    Posts
    1,449

    Re: [2005] My "plan" for dynamic add-on component loading - Thoughts?

    Quote Originally Posted by Naigewron
    Do you know if there is a way for the mother application to ask what interfaces the component implements, or do I have to look for function signatures?
    You'd have to search all types in the loaded assembly and check for the interface you want by using t.GetInterface("my.interface.def").

    The only downside with loading assemblies in the current application domain is that you can't unload them. That is a concern unless you can afford to restart the application in case you have a DLL update - in that case, you wouldn't really care.

    <ParanoidMode>
    Another issue with pluggable applications is security, unless you're the only one that provides signed plugins and you check the plugin signature before creating objects from a plugin. Otherwise, someone could create a plugin that, once loaded in the same app domain, can monkey with your application using Reflection.
    </ParanoidMode>
    "Feel the force...read the source..."
    Utilities: POPFileDebugViewProcess ExplorerWiresharkKeePassUltraVNCPic2Ascii
    .Net tools & open source: DotNetNukelog4NetCLRProfiler
    My open source projects: Thales SimulatorEFT CalculatorSystem Info ReporterVSS2SVNIBAN Functions
    Customer quote: "If the server has a RAID array, why should we bother with backups?"
    Programmer quote: "I never comment my code. Something that is hard to write should be impossible to comprehend."
    Ignorant quote: "I have no respect for universities, as they teach not practicle stuff, and charge money for"

  11. #11

    Thread Starter
    Junior Member
    Join Date
    Jul 2007
    Location
    Bergen, Norway
    Posts
    31

    Re: [2005] My "plan" for dynamic add-on component loading - Thoughts?

    Quote Originally Posted by ntg View Post
    You'd have to search all types in the loaded assembly and check for the interface you want by using t.GetInterface("my.interface.def").
    Hmm, ok, I'll look into it, thanks!

    Quote Originally Posted by ntg View Post
    The only downside with loading assemblies in the current application domain is that you can't unload them. That is a concern unless you can afford to restart the application in case you have a DLL update - in that case, you wouldn't really care.
    Restarting isn't a problem (it's a client application, so users will be opening and closing it constantly), and out on customer sites, updating or adding components will probably happen 1-2 times per year once the system is up and running correctly.

    Quote Originally Posted by ntg View Post
    <ParanoidMode>
    Another issue with pluggable applications is security, unless you're the only one that provides signed plugins and you check the plugin signature before creating objects from a plugin. Otherwise, someone could create a plugin that, once loaded in the same app domain, can monkey with your application using Reflection.
    </ParanoidMode>
    Yeah, this is something we're thinking about as well. We most likely won't make too much hassle around it, but the mother app needs some way to know that the component is "valid" and vice versa.
    Last edited by Naigewron; Mar 18th, 2009 at 04:49 AM.

  12. #12

    Thread Starter
    Junior Member
    Join Date
    Jul 2007
    Location
    Bergen, Norway
    Posts
    31

    Re: [2005] My "plan" for dynamic add-on component loading - Thoughts?

    I suppose this is resolved (for now, hehe)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width