I have an application whose core functionality is contained within a (C) DLL. Header files exist for this library’s exports. This application is very much single-instanced. By that I mean, the library internally uses a lot of global state, as it is only meant to work on one file at a time. The normal workflow the application uses with this library is this:
-
Init
-
Open database
-
Work with database
-
Close database
(Repeat)
I want to write a .NET object model around the functionality this library provides. By this, I mean I want "database" to be an object (call it Database), which has properties/methods that boil down to the library calls.
I would of course want to be able to have multiple Database objects at any given time. However, there can be one instance of this library loaded into my process (I assume), and I am then limited by the library’s use of global variables.
What are my options?
I considered making my top-level class Database accessible only via a factory method, which would limit the number of instances of Database to only one:
public class Database {
private Database() {
library_init();
// ...
}
private Database m_instance;
public static Database Open(string file) {
if (m_instance != null)
throw new InvalidOperationException("...");
return new Database();
}
public Close() {
library_close();
// ...
m_instance = null;
}
}
Is there anything else I can do, like load the library manually in a separate AppDomain or something like that?
I really only foresee needing one instance at a time, but it would be nice to not have to live with that restriction.
If that global state is in RAM only (i.e. the DLL uses no hardcoded file names/registry keys for the state), then I see 2 options how to use several instances:
(quick & dirty) Rename the DLL and load it under another name. This may fail due to many reason, e.g. due to the state of some dependent DLLs, or explicit checks..
(generally more correct, but harder) Create an EXE that loads your C DLL, and exposes the functionality as some IPC API, e.g. as a WCF service with named pipe binding. Then, spawn several instances of that EXE process, and use WCF to call the API.