Two-way IIS 请求内的 AppDomain 之间的通信

Two-way communication between AppDomains inside of IIS Requests

我正在开发一个 ASP.NET 应用程序,我们希望添加在某些请求期间调用客户脚本的功能。由于我们不信任此脚本,因此我们在 IIS 请求中生成了一个 child AppDomain,它具有有限的权限,并加载了客户程序集和脚本运行程序程序集。如果满足某些条件,客户脚本可以执行更改业务描述 object 或将状态代码更改为错误等操作。由于更改如此多样,我无法将它们包含在从方法调用返回的单个 object 中。由于脚本是 运行,我需要它来更改启动此 child.

的请求内的 objects 中的值

post 建议使用 NetNamedPipeBinding,但我越来越担心它不适合 IIS 内部的代码 运行,其中多个请求可能 运行 并发。我会为每个 IIS 请求设置一个新主机吗?为整个过程设置一个静态主机,然后使用端点来确保正确的 child 与正确的请求对话?这是正确的技术吗?

如果这不是正确的技术,那什么才是? post tells you how to retrieve the handle of the parent AppDomain, but many of those seem to use mscoree.dll, and generally I was under the impression that COM and IIS didn't mix terribly well. This post 讨论了清除您的初始 AppDomain 并创建一个新的 AppDomain。也许这在 IIS 中没有必要?

有没有一种方法可以让 child AppDomain 在生成它的请求 object 中有效地执行方法,如果有的话是什么?

我想我已经找到了一个简单的技术 child AppDomain 来改变 parent AppDomain[ 中的状态=21=] 不使用 WCF 或 mscoree.dll。重读上面的第一个 post,我看到他确实提到了它的可能性,但出于我不清楚的原因拒绝了它。诀窍是在 parent 中创建一个从 MarshalByRefObject 派生的 object,获取它的 ObjectHandle,然后将 ObjectHandle 传递给 child AppDomain。然后 child 可以打开句柄以获得代理,然后可以调用将改变 parent 中 object 状态的方法。这是一个代码示例:

class Program
{
    public class ParentFacade : MarshalByRefObject
    {
        public List<string> Collection { get; set; }
        public void AddElement(string el)
        {
            Collection.Add(el);
        }
    }

    public class ChildFacade : MarshalByRefObject
    {
        public void AlterParentState(ObjectHandle handle)
        {
            var parent = handle.Unwrap() as ParentFacade;
            parent.AddElement("Message from child");
        }
    }

    static void Main(string[] args)
    {
        var child = AppDomain.CreateDomain("child");
        var childFacadeType = typeof(ChildFacade);
        var childProxy = child.CreateInstanceAndUnwrap(childFacadeType.Assembly.FullName, childFacadeType.FullName) as ChildFacade;

        var parentColl = new List<string>();
        var facade = new ParentFacade();
        facade.Collection = parentColl;
        var facadeHandle = new ObjectHandle(facade);
        childProxy.AlterParentState(facadeHandle);

        foreach (var item in parentColl)
            Console.WriteLine(item);
    }
}

此代码表明 child 中的方法能够改变 parent 中 object 的状态。这个特定示例不是很有用,但是当您设置沙箱并在您不信任的 child 程序集中包含 .dll 时,它非常有用。不受信任的程序集可以调用 ChildFacade 中的方法,从而以受控和安全的方式改变 parent 中的状态。