Loading a Roslyn compiled assembly into a sandbox AppDomain

谁说我不能喝 提交于 2019-12-02 22:52:50

If you want to load a type that runs in the sandbox and access it from your main AppDomain, you'll need to use a method like CreateInstanceFromAndUnwrap. The type will need to be a MarshalByRefObject so that it can create a transparent proxy in the calling AppDomain for access.

If the main AppDomain resolves the assembly, it will be loaded into the main AppDomain (as well as the sandbox AppDomain) so that you end up with two copies loaded. Your main AppDomain must always remain insulated from the sandbox via proxies, so that only MarshalByRefObject and serializable objects can be accessed. Note that the type you're referencing also cannot be defined in the assembly you want to load into the sandbox; you'll want to define interfaces and possibly serializable types in a third common assembly, which will then be loaded into both the main and sandbox AppDomains.


I've done some additional digging and it looks like all the methods for loading an assembly into another AppDomain and generating a proxy require an assembly name to resolve. I'm not sure if it's possible to load via a byte[] in this case; you might need to save the assembly to disk and load that. I'll dig a bit more.


I think you can do this (this is untested, but it seems plausible).

These would need to be in an 'interface' assembly accessible to both your main app and the sandbox (I'll refer to it as Services.dll):

public interface IMyService
{
    //.... service-specific methods you'll be using
}

public interface IStubLoader
{
    Object CreateInstanceFromAndUnwrap(byte[] assemblyBytes, string typeName);
}

Next is a class in a StubLoader.dll. You won't reference this assembly directly; this is where you'll call the first AppDomain.CreateInstanceFromAndUnwrap, providing 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 your 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 simple to use. This is because they provide a high degree of insulation and therefore require proxying to allow for usage across AppDomain boundaries.


In response to how you could marshal a non-serializable and non-MarshalByRefObject class, here is a rough example of what might be in the shared 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()
    {
        //Do something with the wrapped session...
        //This executes inside the sandbox, even though it can be called (via proxy) from outside the sandbox
    }
}

Now everywhere your original service needed to work with Session, it can instead pass ISessionWrapper, whose calls will be marshalled behind the scenes so that all of the actual code executes in the sandbox on a real Session instance living in the sandbox.

probably this could also help:

https://docs.microsoft.com/en-us/dotnet/framework/misc/how-to-run-partially-trusted-code-in-a-sandbox

Also I had to persist the created assembly file stream onto the disk to get the Sandbox working. I'm still struggling with Strong naming and unit testing of the solution (there are over 16 projects), however, I'll get back to you with the working copy.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!