In short, I wish to load a .DLL file at runtime, and ask it to modify a ref value that I passed to it as a parameter. (the .DLL would be written in C#) but I don't know what a suitable technique would be.
I have a class "ALotOfData" which contains ~1 Gigabyte worth of variables in it.
I want to dynamically load a .DLL file which contains a method
"DoWork(ref ALotOfData thedata){ thedata.value = ... }
then execute the method, and then unload the DLL, and do the same with another DLL. (VERY important to have the ability to load/unload DLLs at runtime)
Obviously, a solution would be to pass a copy of the value itself, return the modified copy, and put it back into my class.
However, this is not possible, if the DLL file will have to make a decision. based on the data, which data to modify (consider: it potentially needs access to all the data).
Merely copying the entire package of data is... an absolutely horrible idea, as the whole entirety of the data is about 1 gigabyte large.
How can I go about importing a method from a .DLL dynamically (at run time) and pass a parameter to it, by ref, and I mean, actually pass a reference, not just copy it? (very important to pass a ref to the class, without copying)
A psuedo-code might help explain my point:
class ALotOfData{ ... } // ~ about 1GB of initialized values inside
Main(){
DLL = loadDLL("mydll.dll");
DLL.Invoke("DoWork",ref AlotOfData); // This needs to actually change my class's contents
DLL.unload();
}
Inside the dll:
DoWork(ref ALotOfData data){
if(data.value){
foreach( value A in data.value ){ ... } // ~100 iterations
}
}
I could add this decision making in my main program, but that would defeat the purpose of being able to load/unload DLL files.
Loading an assembly at runtime is pretty easy:
Unfortunately, there is no way to unload an assembly. Instead you have to unload the entire AppDomain the assembly was loaded into. Normally you have a single AppDomain which contains all your running code; it unloads when your application exits.
If you want to be able to unload assemblies whilst running, you must create a second AppDomain and load your assembly there:
The trouble here is that there is a boundary between AppDomains which has to be crossed to communicate with the objects in each domain.
The problem (as you seem to be aware of) is that the default mechanism for communicating between domains is to create a copy of the object. A complete clone is made and passed into the other domain, which is not suitable when you are working with large amounts of information.
The answer to this problem is the type
MarshalByRefObject
:So, in order to pass your data between domains without creating a bulk copy, the class providing the data needs to inherit from
MarshalByRefObject
. You should also create a type can be loaded in the remote domain which also inherits fromMarshalByRefObject
, so the local domain has a proxy to the remote domain: