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

查看:107
本文介绍了当委托传递给另一个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中的委托的设置器中实例化该类:

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(),它将对任何委托进行动态处理,但是它必须在运行时声明包装类,因为它需要具有正确签名的Invoke方法.

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天全站免登陆