当委托被传递到另一个 AppDomain 时,是否可以将委托编组为代理? [英] Is it possible to have delegates marshalled as proxies when they are passed across to another AppDomain?

查看:22
本文介绍了当委托被传递到另一个 AppDomain 时,是否可以将委托编组为代理?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

不知何故,我假设传递给另一个 AppDomain 的委托会变成代理,就好像它是从 MarshalByRefObject 派生的对象.不幸的是,他们似乎没有.

Somehow I assumed that delegates passed to another AppDomain would turn into a proxy as if it were an object derived from MarshalByRefObject. Unfortunately, it seems they don’t.

假设在我的代码中我有一个类 MyClass 像这样:

Let’s say in my code I have a class MyClass like this:

[Serializable]
public sealed class MyClass
{
    public Func<Input, Output> SomeDelegate;
}

[Serializable]
public sealed class Input { ... }
[Serializable]
public sealed class Output { ... }

现在我需要将 MyClass 的一个实例传递给另一个 AppDomain.

Now I need to pass an instance of MyClass to another AppDomain.

问题是存储在 SomeDelegate 中的委托可能包含对几乎任何方法的引用,包括潜在的类型实例上的方法,它既不是 [Serializable] 也不是从 MarshalByRefObject 派生的.

The problem is that the delegate stored in SomeDelegate may contain a reference to pretty much any method, including potentially a method on an instance of a type that is neither [Serializable] nor derived from MarshalByRefObject.

为了这个问题,我们假设我不能更改创建委托的代码,也不能使 MyClass 成为 MarshalByRefObject.然而,它是[Serializable].

For the sake of this question, let’s assume that I cannot change the code that creates the delegate, nor can I make MyClass a MarshalByRefObject. It is, however, [Serializable].

(请注意,如果 MyClass 包含派生自 MarshalByRefObject 的类型的字段,则存储在该字段中的对象将变成代理,而其余的该类已序列化.)

(Note that if MyClass contained a field of a type that derives from MarshalByRefObject, the object stored in that field would be turned into a proxy, while the rest of the class is serialized.)

是否有什么我可以做的事情可以让我将类作为序列化传递,但是委托变成了代理,就像它是 MarshalByRefObject 一样?(最好在 AppDomain 的设置中这样我就不需要更改 MyClass,但也欢迎涉及更改类的建议,只要我不需要更改创建代表.)

Is there something I can do that will allow me to pass the class as serialized, but with the delegate turned into a proxy, just as it would be if it were a MarshalByRefObject? (Preferably in the setup of the AppDomain so that I don’t need to change MyClass, but suggestions that involve changing the class are welcome too as long as I don’t need to change the code that creates the delegate.)

推荐答案

不幸的是,不能直接使委托本身成为代理.对于远程处理的目的. 我发现一个奇怪的设计决定,因为我认为它违背了委托的逻辑语义,但这是另一回事.

Unfortunately it is not directly possible to make the delegate itself a proxy. Delegates are always by-value objects for the purpose of remoting. I find that a strange design decision as I think it goes against the logical semantics of delegates, but that’s another matter.

为了解决这个问题,我必须将委托包装到一个类中,我可以创建一个 MarshalByRefObject 以便它可以被代理.该类需要有一个与调用委托等效的方法.为了保持干净,我决定将该课程设为私有:

To solve this, I had to wrap the delegate into a class that I can make a MarshalByRefObject so that it would be proxied. That class needs to have a method that is equivalent to invoking the delegate. To keep this clean, I decided to make that class private:

private sealed class myDelegateWrapper : MarshalByRefObject
{
    public Output Invoke(Input input)
    {
        return _delegate(input);
    }

    private Func<Input, Output> _delegate;

    public myDelegateWrapper(Func<Input, Output> dlgt)
    {
        _delegate = dlgt;
    }
}

现在我可以在 MyClass 的委托的 setter 中实例化这个类:

Now I can instantiate this class in the setter of the delegate in MyClass:

[Serializable]
public sealed class MyClass
{
    private Func<Input, Output> _someDelegate;

    public Func<Input, Output> SomeDelegate
    {
        get
        {
            return _someDelegate;
        }
        set
        {
            if (value == null)
                _someDelegate = null;
            else
                _someDelegate = new myDelegateWrapper(value).Invoke;
        }
    }
}

这很迂回,但它满足了我的所有标准:代表仍然可以是任何东西;它将被远程调用(因为它将通过代理包装器);而 MyClass 仍然是 [Serializable] 而不是代理.

This is quite roundabout, but it fulfills all my criteria: The delegate can still be anything; it will be invoked remotely (because it will go through the proxied wrapper); and MyClass is still [Serializable] instead of a proxy.

理论上,可以编写一个扩展方法 Delegate.ToMarshalByRef() ,它可以对任何委托动态执行此操作,但它必须在运行时声明包装类,因为它需要一个 使用正确的签名调用方法.

In theory, one could write an extension method Delegate.ToMarshalByRef() which will do this dynamically with any delegate, but it would have to declare the wrapper class at runtime as it needs an Invoke method with the right signature.

这篇关于当委托被传递到另一个 AppDomain 时,是否可以将委托编组为代理?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆