So I wanted to discuss some challenges I ran into recently. I’m working on some Unity plugins, and these Unity plugins are being distributed as DLLs. There is a common core component, which is distributed with each plugin, and then there are the various plugins. The common core will run with each action, and it checks to see which of the plugins you have, then calls out to those plugins to execute particular functions. So there are a number of requirements here:
The common core has to be the same for each of the plugins
The common core will call into the plugins, if they exist
The plugins themselves may call back into the common core
I don’t control any part of the installation process, so I can’t easily version the common core
So my first thought was to put the common core into a single DLL, and each of the optional plugins into its own DLL. If I put a reference in the common core to each of the plugins, and from each of the plugins to the common core, I can compile it. The issue comes in that the common core will try and load every one of the plugins as soon as it is loaded, and fail if any of them cannot be loaded. This happens before any of our code is executed, and is considered “early binding”. The way to resolve this would be to do “late binding”, which means our code gets executed, and then as is needed, it would load the DLL (if it exists) and allow me to check for the type.
This process is relatively straightforward in C/C++, where it has headers. In those cases I can define the class I am referencing without knowing its particular interface. Here’s where I ran into the first snag, which is that in C#, you don’t have a header file. If I reference a plugin class in the core, that class itself will be included by the core, which would defeat the whole purpose. The two solutions I came up with are I can either manually query and reference each call by a string using reflection (to get the handle that I can use to call the function), or I can create an abstract base class for each object, and have anyone who is “using” the class/object to reference the base type while the actual implementation sits in a derived class. Only the plugin has access to the actual implementation.
The first snag to this comes in that both the plugin and the core class need to reference the interface. If I include it directly, then the class is defined twice (once in the core class, once in the plugin), and this defeats the whole purpose. So the solution is to put the interface class into its own DLL, and I can directly reference that in both the core class and the plugin. I’m calling this a “bridge” class (so that it doesn’t get confused with the language keyword interface).
So the only trouble with creating this sort of bridge class is that I still have a tight coupling between the interface version and the core/plugin. This just means that I need to be very sure about that interface, I can easily update the implementation on either end (you can update your core DLL and/or the plugin DLL, as long as the bridge doesn’t update). If you update the bridge, than the core, and any plugins that use that particular bridge also need to be updated. If the reference is in one direction only, the core calls into the plugin, then you can update your core and *some* of your plugins. If the relationship is two way, where the core calls into the plugin and the plugin calls into the core, then updating the core interface requires updating *all* the plugins that reference it.
Overall, the situation isn’t ideal, and this is one I find much easier to handle in C/C++ code directly (if its an option). I’m really surprised that there isn’t a great system for this in C#, it should be automatic. It looks like Microsoft has a system for this in .NET 4.5, but Unity/Mono doesn’t support that yet, so that’s not an option. How are other people handling this?