我有一个通用的方法
public delegate void Handler<T>(T val);
我允许用户注册事件并提供此委托。 我需要根据类型保存委托列表。
我尝试保存类型和对象的字典。添加方法时,我将其转换为
List<Handler<T>>
根据T.但是当事件发生时我没有T所以不能转换为相关的通用处理程序列表(我确实有类型而不是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 });
}
}
}
}
但问题是这种方法只有在方法是静态的情况下才有效,否则就需要类的类型。
有没有解决这个问题的方法???
启用通用事件... 谢谢!
答案 0 :(得分:3)
也许这会有所帮助:
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);
(这假设我正确地理解了你要做的事情。但我不确定。)
答案 1 :(得分:1)
您还可以使用非泛型委托创建处理程序存储库,例如:
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"