4

私は一般的な方法を持っています

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 });
                }
            }
        }
    }

ただし、問題は、このアプローチが静的な場合にのみ機能することです。そうでない場合は、クラスの型が必要になります。

この問題の解決策はありますか?

一般的なイベントを有効にします...ありがとう!

4

2 に答える 2

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);

(これは、あなたがやろうとしていることを正しく理解していることを前提としています。しかし、よくわかりません。)

于 2013-01-24T08:58:11.877 に答える
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"
于 2013-01-24T09:50:22.550 に答える