tl;dr
Is it possible to include an external library (and create instances of objects represented within that library) based on some condition? This must be done at compile-time, so separate builds?
Background information
Warning: Wall of text.
If I have some code that requires a link to an external class:
using myExternalLibrary;
namespace myNamespace
{
public class Engine
{
public Engine()
{
// external class is contained
// within myExternalLibrary
public externalClass instanceOfExternalClass
= new externalClass();
}
}
}
// external class
namespace myExternalLibrary
{
public class externalClass
{
public externalClass()
{
// constructor logic
}
}
}
By providing references to myExternalLibrary in the project that contains myClass and providing a using statement in a relevant place, I can create an instance of externalClass as and when I need it within myClass. This I am fine with. If I have some very common code that requires several different external libraries, I can do the same thing but with each of the external libraries that are required (i.e add a reference and a using statement for each one of the external libraries).
However, due to the design of the software I am working on, I am required to use an external library only when certain conditions are met. I am also not to include references to those external libraries if they are not required.
Class Detail
I can't go into specifics about the class design, but this is basically what I have: I have a class (this is the Engine class) that is required to act as a bridge between the GUI and some hardware. The Engine class requires external libraries to allow it to communicate with external hardware.
I have two external libraries for two separate types of hardware:
- InternallyDevelopedHardwareControlLibrary (our internally developed hardware library for controlling our internally developed hardware)
- LicensedHardwareControlLibrary (a library that we have licensed for controlling some hardware we have bought in).
By default, the Engine will communicate via InternallyDevelopedHardwareControlLibrary to our internally developed hardware. However, Engine also needs to be able to communicate via LicensedHardwareControlLibrary to the licensed hardware, if (and only if) the end-user has licensed our software to run along side the externally developed hardware.
LicensedHardwareControlLibrary will be licensed to the end-user with our software to some of our end-users. In this instance, LicensedHardwareControlLibrary is required to be shipped with our software. However, if the end-user has is not licensed to use LicensedHardwareControlLibrary, we are not permitted to ship that library with out software.
Since Engine is taking the place of communicating with the external hardware via InternallyDevelopedHardwareControlLibrary by default, it requires a reference to it. However if a user is licensed to utilise LicensedHardwareControlLibrary, I need to add a reference to that, but only if the user is licensed to use that library.
Question
Since Engine is required to be generic, I need to figure out a way of conditionally including this second library.
My initial thought was to move all of the elements of Engine to an abstract class, and to have two separate Engines (one for each of the libraries) that extend the abstract Engine class. Something like:
public class Engine
{
// all common code for each Engine
// type in here
}
public class StandardEngine : Engine
{
// the engine that will utilise
// InternallyDevelopedHardwareControlLibrary
}
public class LicensedEngine : Engine
{
// the engine that will utilise
// LicensedHardwareControlLibrary
}
The StandardEngine code will make use of an instance of the objects represented in InternallyDevelopedHardwareControlLibrary, and LicensedEngine will make use of an instance of the objects represented in LicensedHardwareControlLibrary.
Or more simply put: Each of the less-abstract versions of Engine require to operate on a representation of an object that is contained within either InternallyDevelopedHardwareControlLibrary (StandardEngine) or LicensedHardwareControlLibrary (LicensedEngine).
The standard build will only contain the StandardEngine class, however for some users we will need to run a separate build which also contains the LicensedEngine class.
However, I feel that this will not be optimal because LicensedEngine will need to be external from the main project/library because it cannot be shipped in our standard build. What are the ways in which I can achieve this?
LicensedHardwareControlLibrary
. For those without the special license, simply don't include the actual library assembly into the download (or whatever). If the code never usesLicensedEngine
, it will never attempt to loadLicensedHardwareControlLibrary
and everything will work fine.