0

I am trying to write generic method that all wcf proxy methods go through this method and caches return value. Generic method is

public T CallService<T>(Delegate del, object[] args)
{
    // begin caching logic
    // ...
    // if value is cached, return it. Otherwise call app site.       
    // end caching logic
    return (T)del.DynamicInvoke(args);
}

To achieve this, I need to create delegate dynamically with the help of link below.

Creating delegates dynamically with parameter names

Briefly what I want is to create delegate for channel method IFooService.Bar(string param).

//wcf contract
public interface IFooService
{
   int Bar(string param);
}

//sample proxy
public class Foo
{
    public int Bar(string param)
    {
        IFooService channel = null;
        int result;
        try
        {
            // we assume that wcf channel has created here
            ChannelFactory<IFooService> channelFactory = new ChannelFactory<IFooService>(binding, remoteAddress);
            IFooService channel = channelFactory.CreateChannel();

            var parameters = MethodBase.GetCurrentMethod().GetParameters();
            object[] args = new object[parameters.Length];
            args[0] = param;          

            MethodInfo method = typeof(IFooService).GetMethod("Bar");
            Delegate del = CreateDelegate(channel, method);

            result = CallService<int>(del, args);
            ((ICommunicationObject)channel).Close();
        }
        catch (Exception ex)
        {
            ((ICommunicationObject)channel).Abort();
            throw;
        }
        return result;
    }
}

When application runs, I get the exception at the line "Delegate del = CreateDelegate(channel, method)".

Cannot bind to the target method because its signature or security transparency is not compatible with that of the delegate type.
       at System.Delegate.CreateDelegate(Type type, Object firstArgument, MethodInfo method, Boolean throwOnBindFailure)

I believe method signature is correct.

Channel object's exact type is System.Runtime.Remoting.Proxies.__TransparentProxy. However, channel.getType() returns IFooService. How can this can be possible ? What is the magic behind this situation? I wonder the pattern provides this solution and how __TransparentProxy works. Is there any code(project) sample demonstrates this architecture ? I think that's why dynamic delegate creation could not bind the target method.

Community
  • 1
  • 1
Oytun Yilmaz
  • 101
  • 2
  • 9

1 Answers1

2

I got the same exception when I tried

MethodInfo mi = typeof(IMyInterf).GetMethod(MyMethod);
Delegate d = Delegate.CreateDelegate(typeof(myMethodDelegate), channel, mi);
d.DynamicInvoke(args);

It works when I change this to:

Delegate d = Delegate.CreateDelegate(typeof(myMethodDelegateX), null, mi);
d.DynamicInvoke(channel, args);

If myMethodDelegate looks like

delegate void myMethodDelegate(T1 arg1, T2 arg2, ...);

then myMethodDelegateX must have the instance parameter for which you pass channel as first argument, followed by the actual method arguments, according to the .DynamicInvoke call:

delegate void myMethodDelegateX(IMyInterf targetInstance, T1 arg1, T2 arg2, ...);

I found this variant in the MSDN documentation on the Delegate.CreateDelegate(Type, Object, MethodInfo) overload, it is called an "open instance" method there, and it works with my WCF channel, where I always got "cannot bind to target method..."

EDIT: Of course d.DynamicInvoke(channel, args) is nonsense, you have to put these arguments into a new array.

Christoph
  • 712
  • 1
  • 6
  • 17