Search code examples
c#genericsdelegatesmethodinfomethod-invocation

Handle Generic methods in a dictionary according to type


I have a generic method

public delegate void Handler<T>(T val);

I enable users to register to events and provide this delegate. I need to save the list of delegate according to their types.

I tried saving in a dictionary of Type and object. when adding the method I cast it to a

List<Handler<T>>

according to the T. but then when an event occurred I do not have the T so cannot cast to the relevant list of generic handlers (I do have the Type but not the T)

I solved this by saving methodInfo list for each type

  private Dictionary<Type, List<MethodInfo>>  handlers = new Dictionary<Type, List<MethodInfo>>();

    public delegate void Handler<T>(T val);


    public void Register<T>( Handler<T> handler )
    {
        List<MethodInfo> lst;
        if (!handlers.TryGetValue(typeof(T), out lst))
        {
            lst = new List<MethodInfo>();
            handlers.Add(typeof(T), lst);
        }
       lst.Add(handler.Method);

    }

    public void RaiseEvent( string value)
    {
       foreach (KeyValuePair<Type, List<MethodInfo>> pair in handlers)
            {
                object typedValue;

                if (pair.Key.IsEnum)
                {
                    typedValue = Enum.Parse(pair.Key, value);
                }
                else
                {
                    typedValue = Convert.ChangeType(value, pair.Key);
                }

                foreach (MethodInfo  methodInfo  in pair.Value )
                {
                    methodInfo.Invoke(null, new[] { typedValue });
                }
            }
        }
    }

but the problem is that this approach will work only if the method is static , otherwise it will require the type of class.

is there any solution for this problem???

enable generic events... thanks!


Solution

  • Maybe this will help:

    public delegate void Handler<in T>(T val);
    
    private List<Delegate> m_list = new List<Delegate>();
    
    public void AddListener<T>(Handler<T> handler) {
      m_list.Add(handler);
    }
    
    public void Call(object eventArg) {
      foreach (var handler in m_list) {
        handler.DynamicInvoke(eventArg);
      }
    }
    

    Then, if you have a handler like this:

    private void MyHandler(int val) {
      // Do something
    }
    

    You can add it to the list like this:

    AddListener<int>(MyHandler);
    

    (This assumes I correctly understood what you're trying to do. I'm not sure though.)