Is it possible to have delegates marshalled as proxies when they are passed across to another AppDomain?

微笑、不失礼 提交于 2019-12-06 14:33:03

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.

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;
    }
}

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;
        }
    }
}

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.

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.

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