Question

I am looking for a way to isolate a component (based on a 3rd party dll) in a separate AppDomain that can be unloaded. My plan was to use CreateInstanceAndUnwrap and MarshalByRefObject-based objects for communication with the component.

The problem is that in order to use objects derived from MarshalByRefObject in the main assembly it has to reference the component dll and I am trying to avoid that. I thought I might decouple it via an interface

class MyObject: MarshalByRefObject, IMyObject
{
}

but I cannot cast the object returned from CreateInstanceAndUnwrap to IMyObject (because it is actually a proxy, not a real object I guess?).

Am I missing something, or this just can't be done and the only answer is WCF?

Update: The actual issue that I had was that IMyObject was defined twice: I had the file included in the main assembly and in the component assembly. This way I get an exception "Unable to cast transparent proxy to type". When I am using only one interface/class definition that I reference from both assemblies, it works fine (both as Will suggested and as I described above).

Was it helpful?

Solution

Eh, interfaces kinda suck anyhow.

Ditch it and go with an abstract base class that inherits from MBRO.

public abstract class MyObject : MarshalByRefObject
{
    protected MyObject() : base() {}
    public abstract void LoadPluginAssemblyLol();
    public abstract void ExecuteSuperCollider();
}

Pull that back across the boundary and control the plugin that way. Also, remember not to expose events on the type (event subscribers get pulled across boundaries without you realizing it) and you should probably only take method arguments and have return values that are primitives or strictly controlled so that you don't accidentally end up with the dll loaded in your main domain.

Another issue you'll run into is that you have to manage the lifespan of objects that are proxied via an ISponsor implementation. Otherwise the instance in the host domain gets collected after 10 minutes.

As for using MyObject, you would...

// assume an implementation such as 'class MyObjectImplementation : MyObject {...}'

var type = typeof(MyObjectImplementation);
var newDomain = CreateNewAppDomainKthx();
var controller = newDomain
    .CreateInstanceAndUnwrap(
        type.Assembly.FullName, 
        type.FullName) as MyObjectImplementation;
controller.LoadPluginAssemblyLol();
controller.ExecuteSuperCollider();
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top