Обработка универсальных методов в словаре в соответствии с типом
У меня есть общий метод
public delegate void Handler<T>(T val);
Я даю пользователям возможность зарегистрироваться на мероприятия и предоставить этого делегата. Мне нужно сохранить список делегатов в соответствии с их типами.
Я попытался сохранить в словаре типа и объекта. при добавлении метода я бросил его в
List<Handler<T>>
в соответствии с T. но затем, когда произошло событие, у меня нет T, поэтому я не могу привести его к соответствующему списку универсальных обработчиков (у меня есть Type, но не T)
Я решил это, сохранив список methodInfo для каждого типа
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 });
}
}
}
}
но проблема в том, что этот подход будет работать только в том случае, если метод является статическим, в противном случае ему потребуется тип класса.
есть ли решение для этой проблемы???
включить общие события... спасибо!
2 ответа
Может быть, это поможет:
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);
}
}
Затем, если у вас есть такой обработчик:
private void MyHandler(int val) {
// Do something
}
Вы можете добавить его в список следующим образом:
AddListener<int>(MyHandler);
(Это предполагает, что я правильно понял, что вы пытаетесь сделать. Хотя я не уверен.)
Вы также можете создать репозиторий обработчиков, используя неуниверсальный делегат, что-то вроде:
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);
}
}
и используйте это так:
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"