问题
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!
回答1:
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.)
回答2:
You could also make a handler repository using a non-generic delegate, something like:
public delegate void Handler(object val);
public delegate void Handler<T>(T val);
public class HandlerRepository
{
private Dictionary<Type, Handler> handlers = new Dictionary<Type, Handler>();
public void RegisterHandler<T>(Handler<T> handler)
{
//error checking omitted
//create a non-generic handler that calls the generic handler
//with the correct type.
handlers.Add(typeof(T), (value)=>handler((T)value));
}
public void ExecuteHandler<T>(T value)
{
//error checking ommited
handlers[typeof(T)](value);
}
}
and use it like this:
Handler<int> handleInt = value => Console.WriteLine("Int32 is {0}", value);
Handler<string> handleString = value => Console.WriteLine("String is {0}", value);
HandlerRepository repo = new HandlerRepository();
repo.RegisterHandler(handleInt);
repo.RegisterHandler(handleString);
//this call boxes the argument to an object
repo.ExecuteHandler(5); // "Int32 is 5"
repo.ExecuteHandler("Hello, world"); "String is Hello, world"
来源:https://stackoverflow.com/questions/14496989/handle-generic-methods-in-a-dictionary-according-to-type