1

我正在尝试创建一个 RealProxy 以实现一些缓存和一些其他功能。我检查了 GetTransparentProxy 返回的类型,它看起来是正确的,但是如果我在它上面调用 InvokeMember,那么代理最终会调用自己并且我得到一个堆溢出。请有人指出我做错了什么?

public class CachedWebServiceProxy<T> : RealProxy
{
    private Type _typeOfProxy;
    public CachedWebServiceProxy(Type typeOfProxy) : base(typeOfProxy)
    {
        _typeOfProxy = typeOfProxy;
    }
    public override System.Runtime.Remoting.Messaging.IMessage Invoke(System.Runtime.Remoting.Messaging.IMessage msg)
    {
        var methodCall = msg as IMethodCallMessage;
        var methodInfo = methodCall.MethodBase as MethodInfo;

        var proxy = GetTransparentProxy();
        var result = _typeOfProxy.InvokeMember(methodCall.MethodName, BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Instance, null, proxy, methodCall.Args);
        return new ReturnMessage(result, null, 0, methodCall.LogicalCallContext, methodCall);
    }
}

class CachedWebServiceChannelFactory<T> : ChannelFactory<T>
{
    public CachedWebServiceChannelFactory(Binding binding, EndpointAddress endpoint) : base(binding, endpoint) 
    { }

    public CachedWebServiceChannelFactory(string endpointConfigurationName)
        : base(endpointConfigurationName)
    { }

    public override T CreateChannel(EndpointAddress address, Uri via)
    {
        var extendedProxy = new CachedWebServiceProxy<T>(typeof(T));
        return (T)extendedProxy.GetTransparentProxy();
    }
}
4

1 回答 1

1

好的,基本问题是我假设我的代码正在包装透明代理,而实际上透明代理正在包装我的类。我认为我可以做的是创建一个基本代理的实例,调用这个代理上的方法并返回结果。

因为我的类实际上是调用 GetTransparentProxy 的透明代理的基类,所以刚刚创建了我的类的一个新实例(它又创建了另一个新实例等)

我现在意识到我应该在 ChannelFactory 中做类似的事情。这是一个子类,所以我可以在我自己的逻辑中包装 base.* 方法,就像我希望在代理类中做的那样。我现在要做的是从基础方法中获取通道的实例,然后将其传递给我的 RealProxy 类,然后使用反射在通道对象上调用所需的方法。

这是代码:

public class CachedWebServiceProxy<T> : RealProxy
{
    private Type _typeOfProxy;
    public object _channel;
    public CachedWebServiceProxy(Type typeOfProxy, object channel)
        : base(typeOfProxy)
    {
        _typeOfProxy = typeOfProxy;
        _channel = channel;
    }
    public override System.Runtime.Remoting.Messaging.IMessage Invoke(System.Runtime.Remoting.Messaging.IMessage msg)
    {
        var methodCall = msg as IMethodCallMessage;
        var methodInfo = methodCall.MethodBase as MethodInfo;
        object result = null;
        result = methodInfo.Invoke(_channel, methodCall.Args);
        return new ReturnMessage(result, null, 0, methodCall.LogicalCallContext, methodCall);
    }
}


public class CachedWebServiceChannelFactory<T> : ChannelFactory<T>
{
    public CachedWebServiceChannelFactory(Binding binding, EndpointAddress endpoint)
        : base(binding, endpoint)
    { }

    public CachedWebServiceChannelFactory(string endpointConfigurationName)
        : base(endpointConfigurationName)
    { }

    public override T CreateChannel(EndpointAddress address, Uri via)
    {
        T innerChannel = base.CreateChannel(address, via);
        var extendedProxy = new CachedWebServiceProxy<T>(typeof(T), innerChannel);
        return (T)extendedProxy.GetTransparentProxy();
    }
}

于 2013-07-08T08:43:52.887 回答