Reputation: 1425
I'm trying to create a RealProxy in order to implement some caching and a few other functions. I've checked the Type that GetTransparentProxy returns and it looks correct, however if I call InvokeMember on it then the proxy ends up calling itself and I get a heap overflow. Please could someone point out what I'm doing wrong?
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();
}
}
Upvotes: 1
Views: 301
Reputation: 1425
Ok, the basic issue was that I assumed that my code was wrapping the transparent proxy when in fact the transparent proxy is wrapping my class. I thought that what I could do is create an instance of the base proxy, call methods on this proxy and return the results.
Because my class is actually the base class for transparent proxy calling GetTransparentProxy just created a new instance of my class (which in turn created another new instance etc.)
I now realize that I should have been doing a similar kind of thing but within the ChannelFactory instead. This is a subclass so I can just wrap base.* methods in my own logic as I had hoped to do within the proxy class. What I now do is get an instance of the channel from a base method, I then pass it in to my RealProxy class and then use reflection to call the required method on the channel object.
Here is the code:
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();
}
}
Joe
Upvotes: 1