If you want to load a type that runs in the sandbox and access it from the main AppDomain, you need to use a method like CreateInstanceFromAndUnwrap . The type must be MarshalByRefObject so that it can create a transparent proxy in the calling AppDomain application for access.
If the main AppDomain allows the build, it will be uploaded to the main AppDomain (as well as to the Sandbox AppDomain) so that you end up downloading two copies. Your main AppDomain should always remain isolated from the sandbox through proxies so that you can only access MarshalByRefObject objects and serializable objects. Please note that the type you are referencing also cannot be defined in the assembly you want to load into the sandbox; you will want to define the interfaces and possibly serializable types in the third general assembly, which will then be loaded into both the main and sandboxes of the AppDomains.
I did some additional digging, and it seems that all methods of loading the assembly into another AppDomain and creating a proxy require the assembly name to resolve. I am not sure if it is possible to load via byte [] in this case; You may need to save the assembly to disk and load it. I will dig a little more.
I think you can do it (this is untested, but seems plausible).
They should be in the "interface" assembly, available both for your main application and for the sandbox (I will call it as Service.dll):
public interface IMyService {
Next is the class in StubLoader.dll. You will not refer to this assembly directly; here you will call the first AppDomain.CreateInstanceFromAndUnwrap, specifying this as the assembly name and StubLoader as the type name.
public sealed class StubLoader: MarshalByRefObject, IStubLoader { public object CreateInstanceFromAndUnwrap(byte[] assemblyBytes, string typeName) { var assembly = Assembly.Load(assemblyBytes); return assembly.CreateInstance(typeName); } }
Now, to use it from the main AppDomain, you do this:
//Create transparent proxy for the stub loader, which will live in the sandbox var stubLoader = (IStubLoader)sandboxDomain.CreateInstanceFromAndUnwrap("Stubloader.dll", "StubLoader"); //Have the stub loader marshal a proxy to a dynamically loaded assembly (via byte[]) where MyService is the type name implementing MarshalByRefObject and IMyService var myService = (IMyService)stubLoader.CreateInstanceFromAndUnwrap(assemblyBytes, "MyService");
Unfortunately, AppDomains are not easy to use. This is due to the fact that they provide a high degree of isolation and, therefore, require proxying for use within the boundaries of AppDomain.
In response to how you could marshal a non-serializable and non-MarshalByRefObject class, here is an example of what might be in a common interface DLL:
public interface ISessionWrapper { void DoSomethingWithSession(); } public sealed class SessionWrapper : MarshalByRefObject, ISessionWrapper { private readonly Session _session; public SessionWrapper(Session session) { _session = session; } public void DoSomethingWithSession() {
Now that your original service needs to work with the session, it can instead pass ISessionWrapper, whose calls will be sorted behind the scenes so that all executable code is executed in the sandbox in a real session instance living in the sandbox.