views:

239

answers:

2

I need to convert an open delegate (one in which the Target is not specified) into a closed one efficiently. I have profiled my code, and the cost of using CreateDelegate() to produce a closed delegate for an instance method is a significant fraction (>60%) of the overall run time (as it takes place for each new instance of the type).

Some basic information about open and closed delegates is described on the MSDN site in the documentation for CreateDelegate.

My current approach, is to find a way to cache the open delegate (so the cost of producing it is incurred just once) and invoke it using another method that supplies the implicit "this" parameter to the delegate.

A complicating factor is that I don't know the signature of the method that the delegate will represent at compile-time, other than through a generic parameter in the code. In addition, I want to avoid reflection (e.g. Invoke() and DynamicInvoke()) as they are no better in terms of performance.

static TDel CreateOpenDelegate<TDel>( MethodInfo mi )
{
    // creates and returns an open delegate for a delegate of signature TDel
    // that will invoke some method as described by MethodInfo {mi}
    return (TDel)(object)Delegate.CreateDelegate( typeof(TDel), mi );
}

// simplification of some other code...
// Note that Action<T> is a sample usage, the actual delegate signature and
// invocation parameters vary, and are defined by the consumers of my code
private Action<T> myAction = CreateOpenDelegate<Action<U,T>>( someMethodInfo );
myAction( this, default(T) ); // can't do this since {this} is a hidden parameter...

I have already read Jon Skeet's article on Making Reflection Fly and Exploring Delegates, unfortunately, since I don't know the delegate signature in advance, I don't see a way to adapt the approach described there.

Any help would be appreciated.

A: 

Are you trying to convert a delegate or a MethodInfo to a closed delegate?

If you're trying to convert a delegate to a closed delegate, how about currying, like this?

static Action<T2> Curry<T1, T2>(Action<T1, T2> del, T1 obj) { return p => del(obj, p); }
SLaks
Unfortunately, I don't know the method signature in advance, so I can't explicitly curry parameters in this way. Action<> could be any arbitrary delegate defined by a consumer of my code.
LBushkin
If so, what delegate type do you want to curry to? Or will you have two generic parameter>
SLaks
+2  A: 

If I understand your requirements correctly, you could probably use expression trees to accomplish this - I have a post exploring the topic here*. Here's a simplified version:

public static D GetMethodAccessor<D>(MethodInfo mi) where D : class
{
    Type[] args = typeof(D).GetGenericArguments();
    if (args.Length == 0)
        throw new ArgumentException("Type argument D must be generic.");

    Type instanceType = args[0];

    // If return type is not null, use one less arg
    bool isAction = mi.ReturnType == typeof(void);
    int callArgCount = args.Length - (isAction ? 1 : 2);
    Type[] argTypes = args.Skip(1).Take(callArgCount).ToArray();

    var param = Expression.Parameter(instanceType, "obj");
    var arguments = argTypes.Select((t, i) => Expression.Parameter(t, "p" + i))
                            .ToArray();
    var invoke = Expression.Call(param, mi, arguments);
    var lambda = Expression.Lambda<D>(invoke,
                     Enumerable.Repeat(param, 1).Concat(arguments));

    Debug.WriteLine(lambda.Body);
    return lambda.Compile();
}

All that said, I'm not sure how the additional type argument processing and expression compilation would compare with your method.

As far as providing the implicit 'this', could use use extension methods?

private static Action<U,T> myAction = GetMethodAccessor<Action<U,T>>(myMethod);
public static void MyAction<U,T>(this U u, T t)
{
    myAction(u, t);
}

*Note that the string-based dictionary cache I use in the post is terribly inefficient - you'll want to cache the delegate to a private instance like in your example.

dahlbyk