1

キャッシングとその他のいくつかの機能を実装するために、RealProxy を作成しようとしています。GetTransparentProxy が返す Type を確認しましたが、正しいように見えますが、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

OK、基本的な問題は、実際には透過プロキシがクラスをラップしているときに、コードが透過プロキシをラップしていると想定していたことです。私にできることは、ベース プロキシのインスタンスを作成し、このプロキシでメソッドを呼び出して結果を返すことだと考えました。

私のクラスは実際には透過プロキシの基本クラスであるため、 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 に答える