How to determine delegate type at runtime (i.e. dynamic delegate type)

To create delegates on the fly, methods range from Delegate.CreateDelegate, Expresion Lambda, DynamicMethod, etc. etc. All of these methods require you to know the type of delegate.

I am trying to convert private delegates to open delegates in the general case, and to achieve this it seems to me that I need to dynamically create an open delegate type before I can create the resulting delegate. Consider:

pubic class WeakEvent<TDelegate> where TDelegate : class
{
     public WeakEvent(Delegate aDelegate)
     {
         var dgt = aDelegate as TDelegate;

         if(dgt == null)
             throw new ArgumentException("aDelegate");

         MethodInfo method = dgt.Method;
         var parameters = Enumerable
                         .Repeat(dgt.Target.GetType(),1)
                         .Concat(method.GetParameters().Select(p => p.ParameterType));

         Type openDelegateType = // ???  original delegate, with new 1st arg for @this

         var dm = new DynamicMethod("InnerCode", method.ReturnType, parameters);

         ... your favourite IL code emmisions go here

         var openDelegate = dm.CreateDelegate(openDelegateType);
     }
}

The navel of the above code is to create a new delegate that is identical to the original delegate, but has a new 1st argument for this ... that is, an open version of a previously closed delegate.

Func < > Action < > ?

+3
3

@Mark - :

, ( ), [re] ref out, generics Func Action .

, . # ref Ani: Expression.GetDelegateType ref.

0

- . #, , , , - , .

, , Action < > Func < > . .

+1

, - , :

    private Type CreateOpenDelegate()
    {
        var parms = _method.GetParameters();
        bool hasReturn = _method.ReturnType != typeof (void);
        Type generic = GetGenericTypeForOpenDelegate(parms, hasReturn);

        var argTypes = new List<Type>(parms.Length + 2) {_method.DeclaringType};

        foreach (var arg in parms)
        {
            if(arg.IsOut || arg.IsRetval)
                throw new NotImplementedException();

            argTypes.Add(arg.ParameterType);
        }

        if(hasReturn)
            argTypes.Add(_method.ReturnType);

        var result = generic.MakeGenericType(argTypes.ToArray());

        return result;
    }

    private static Type GetGenericTypeForOpenDelegate(ParameterInfo[] parms, bool hasReturn)
    {
        if (hasReturn)
        {
            switch (parms.Length)
            {
                case 0:
                    return typeof (Func<,>);
                    break;
                case 1:
                    return typeof (Func<,,>);
                    break;
                case 2:
                    return typeof (Func<,,,>);
                    break;
                case 3:
                    return typeof (Func<,,,,>);
                    break;
            }
        }
        else
        {
            switch (parms.Length)
            {
                case 0:
                    return typeof (Action<>);
                    break;
                case 1:
                    return typeof (Action<,>);
                    break;
                case 2:
                    return typeof (Action<,,>);
                    break;
                case 3:
                    return typeof (Action<,,,>);
                    break;
            }
        }
        throw new NotImplementedException();
    }

, ( ), ref out, generics Func Action .

+1

Source: https://habr.com/ru/post/1771665/


All Articles