2

私は次のようなクラスを持っています:

public static class Messenger<T>
{
    private static readonly Dictionary<string, Delegate> eventTable = new Dictionary<string, Delegate>();
    public static void DoSomethingWithEventTable() //Somehow fills eventTable
    public static void Clear() 
    {
        eventTable.Clear();
    }
}

さて、次DoSomethingWithEventTableのように、プログラムのどこかで 2 回呼び出しました。

Messenger<int>.DoSomethingWithEventTable();
Messenger<float>.DoSomethingWithEventTable();

eventTableごとにクリアしたいMessenger<T>。どうすればいいですか?Clear次のように、ジェネリックに入れているすべての型を呼び出す必要があります。

Messenger<int>.Clear();
Messenger<float>.Clear();

それとも、次のようなばかげたことを一度するだけで十分でしょうか。

Messenger<string>.Clear();

UPD:基本的な実験では、T を使用するたびに Messenger をクリアする必要があることが示されています。クラスのより良い設計ができる人はいますか?

私が現在使用しているもののより詳細なバージョン:

static public class Messenger<T>
{
    private static readonly Dictionary<string, Delegate> eventTable = new Dictionary<string, Delegate>();

    static public void AddListener(string eventType, Callback<T> handler)
    {
        // Obtain a lock on the event table to keep this thread-safe.
        lock (eventTable)
        {
            // Create an entry for this event type if it doesn't already exist.
            if (!eventTable.ContainsKey(eventType))
            {
                eventTable.Add(eventType, null);
            }
            // Add the handler to the event.
            eventTable[eventType] = (Callback<T>)eventTable[eventType] + handler;
        }
    }

    static public void RemoveListener(string eventType, Callback<T> handler)
    {
        // Obtain a lock on the event table to keep this thread-safe.
        lock (eventTable)
        {
            // Only take action if this event type exists.
            if (eventTable.ContainsKey(eventType))
            {
                // Remove the event handler from this event.
                eventTable[eventType] = (Callback<T>)eventTable[eventType] - handler;

                // If there's nothing left then remove the event type from the event table.
                if (eventTable[eventType] == null)
                {
                    eventTable.Remove(eventType);
                }
            }
        }
    }

    static public void Invoke(string eventType, T arg1)
    {
        Delegate d;
        // Invoke the delegate only if the event type is in the dictionary.
        if (eventTable.TryGetValue(eventType, out d))
        {
            // Take a local copy to prevent a race condition if another thread
            // were to unsubscribe from this event.
            Callback<T> callback = (Callback<T>)d;

            // Invoke the delegate if it's not null.
            if (callback != null)
            {
                callback(arg1);
            }
        }
    }

    static public void Clear()
    {
        eventTable.Clear();
    }
}

Messengerまた、別のクラス(非ジェネリック、ええ) とを持っていることも重要です。Messenger<T,M>いつかMessenger<T,M,N>、 などのようなものが必要になるかもしれません。

4

2 に答える 2

3

Messenger<T>タイプには独自の eventTable のコピーがあるため、使用した異なる T ごとに Clear() を呼び出す必要があります。

このテストで示されるように:

[TestFixture]
    public class Tests
    {    
        static class MyClass<T>
        {
            public static List<int> Member = new List<int>();
        }

        [Test]
        public void StaticTest()
        {
            var m1 = MyClass<int>.Member;
            var m2 = MyClass<string>.Member;

            Assert.AreNotSame(m1, m2);
        }
}
于 2012-10-26T06:50:20.333 に答える
3

以来

private static readonly Dictionary<string, Delegate> eventTable = new Dictionary<string, Delegate>();

に依存しない<T>ため、すべてのイベント テーブルに対して静的な「ハンドラ」を作成します。

IE

public static class TableHandler {
    ICollection<Dictionary<string, Delegate>> tables = new List<Dictionary<string, Delegate>>();

    public void Add(Dictionary<string, Delegate> item) 
    {
        tables.Add(item);
    }

    public void Clear()
    {
        foreach (var item in tables) item.Clear();
        tables.Clear();
    }
}

DoSomethingWithEventTable()にイベント テーブルが追加されていることを確認しますTableHandler

全体的には最善の解決策ではないかもしれませんが、現在の設計でテーブルを追跡するのに役立ちます。

編集:

静的クラスのすべての汎用バリアントを見つける方法をグーグルで検索しようとしましたが、方法が見つかりませんでした。誰もそれを行う方法を知っていますか?

于 2012-10-26T06:55:04.733 に答える