我有一个通用方法
public delegate void Handler<T>(T val);
我使用户能够注册事件并提供此委托。我需要根据委托的类型保存委托列表。
我尝试保存在类型和对象的字典中。 添加方法时,我将其转换为
List<Handler<T>>
根据 T. 但是当事件发生时,我没有 T,因此无法强制转换为相关的泛型处理程序列表(我有类型但没有 T)
我通过保存每种类型的方法信息列表来解决这个问题
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 });
}
}
}
}
但问题是这种方法只有在该方法是静态的时才有效,否则它将需要类的类型。
这个问题有什么解决方案吗???
启用通用事件...谢谢!
也许这会有所帮助:
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"