3

MessengerClientクラスにはLogin関数があります。MessengerClientクラスには、LoggedInイベントIsLoggedInプロパティがあります。

MessengerClientクラスでLoginが呼び出されると、連絡先リスト/名簿がソケットを介してリモート サーバーから取得され、処理されます。その後、クライアントはログインしていると見なされ、IsLoggedInは true を返します。LoggedInイベントは、この後に Login 関数内で発生します (したがって、ログインを要求する同じスレッド内で発生します。これは悪いことではないと思います)。

ログインすると、クライアントはリモート サーバーからライブ更新を受信します。

ログイン中に連絡先リスト/名簿を処理する場合、エンド ユーザーにとって理想的な設計は、クライアントがログインしていると見なされる前に、すべての連絡先リスト/名簿データを処理することだと思います。このようにして、ユーザーがLoggedInイベントを受け取ると、すぐに連絡先データにアクセスできます。

例えば ​​-

ここには、LoggedInイベントに対するエンド ユーザーのハンドラーがあります。

    void MsgrLoggedIn(object sender, EventArgs a)
    {
        _msgr.Contacts.Contains("billy@bob.com"); //returns true
    }

クライアントがログイン済みとしてマークされる前、およびLoggedInイベントが発生する前に、すべての連絡先リストが処理されているため、上記のステートメントは true を返します。論理的には、連絡先リストのダウンロードと処理はログイン操作の一部であるため、これはエンド ユーザーが期待することだと思います。

また、連絡先が連絡先リストに追加されたとき、またはグループに追加されたときにイベントを発生させることも好きです。これまでに述べたロジックからすると、データが処理されているときにContactAddedContactAddedToGroupなどのイベントを発生させることは明らかに意味がありません。これにより、MessengerClient クラスが処理される前にエンド ユーザーがこれらのイベントのいずれかを受け取ることになるためです。ログイン中としてマークされます。

    void MsgrContactAdded(object sender, ContactEventArgs e)
    {
        _msgr.SendMessage(e.Contact, "hello there"); // throws NotLoggedInException
    }

上に示したように、これは悪いことが起こる結果になります。

したがって、私が実際に行う必要があるのは、連絡先リストのデータを処理し、logged in イベントを発生させ、その後で他のすべての連絡先イベントを発生させることです。

このために、すべての連絡先オブジェクト、グループ オブジェクトなどを反復処理して、適切なイベントを発生させることができます。

ここまでは大丈夫ですよね?

ただし、問題は、最初のログイン時に連絡先リストのデータをダウンロードすることに加えて、クライアントがログアウトしてから再度ログインした場合に連絡先データを同期する準備をしなければならないことです。

これには、ContactRemoved、ContactNameChanged、ContactRemovedFromGroup などのイベントが含まれます。

そのため、削除された連絡先やプロパティが変更された連絡先を考慮する必要があるため、連絡先やグループなどを反復処理するほど単純ではなくなりました。

したがって、ログインが行われた後にこれらのイベントが発生するように「キューに入れる」別の方法が必要です。

各同期イベントを表すクラスを用意することを検討しました。たとえば、SyncContactRemoved、SyncContactNameChanged、SyncContactAddedToGroup などです。これにより、データを処理し、イベントごとに Sync*XXX* クラスを作成し、それらをリストに追加して、ログイン後に反復できるようにします。

オブジェクト自体にメソッドを持たせることも検討しました。つまり、Group.SyncContactsAdded、Contact.SyncNameChanged、MessengerClient.SyncContactsAdded です。次に、ログイン後に連絡先/グループなどを繰り返し処理し、これらのプロパティを確認し、必要に応じてイベントを発生させてからクリアします。

最後に、EventHandler と EventArgs を含む Event クラスを持つことを検討しました。この方法でイベントをキューに入れ、ログイン後に 1 つずつ呼び出すことができます。

もしあれば、これらのパターンのどれがより一般的な方法と考えられますか. または、これを達成するための代替手段はありますか?

とても長い質問で申し訳ありませんが、簡単な質問ではありません。

ありがとう

4

4 に答える 4

0

結局、イベントをリストに保存して、後でそれらを上げることになりました。

List<SomethingEventArgs> events;

foreach (SomethingEventArgs e in events)
    OnSomethingEvent(e);

私が好きだったほど魅力的ではありませんが、それは非常に理にかなっており、完璧に機能します。

于 2012-04-26T01:17:24.783 に答える
0

これらのパターンのうち、より一般的な方法と考えられるものはどれですか。または、これを達成するための代替手段はありますか?

つまり、最初の連絡先がオフラインである間に、特定の連絡先の連絡先で発生するすべてのイベントをキューに入れたいですか? そのため、連絡先 A の連絡先リストには連絡先 B が含まれていますが、現時点では連絡先 A はオフラインです。連絡先 B がプロファイルを変更したContactNameChangedので、そのイベント (など) を連絡先 A のキューに入れたいですか?

私はそのようにはしません。連絡先 A が連絡先 B のデータをいつ受信したかを示す、ある種の同期トークン (日時で問題ありません) を保存したいと思います。すべての連絡先にはLastModifiedプロパティがあり、それを同期トークンと比較します。前回の同期以降に何らかの変更が加えられた場合は、変更された連絡先の完全な詳細を取得するためのリクエストを行います。

削除された連絡先の場合、2 つのリストを交差させることができます。クライアントが現在のリストであると考える連絡先リストを持つものと、サーバーからの最新のリストの 1 つです。それらを比較すると、追加と削除が行われ、このリストをループしながら、上記のLastModified-datetimes を比較することもできます。

于 2012-04-18T09:37:03.837 に答える
0

States のデザイン パターンを確認する必要があると思います。クライアントが次のように毎回異なる状態になることを考慮してください。

この状態のログイン状態では、LoginFailed や LoginSucceed などのいくつかの特別なイベントが生成されます。また、この状態では Login メソッドが 1 つしか提供されません。

ユーザーがメッセージを受け入れてグループに送信するチャット状態。

そして、あなたが必要とするものは何でも。

したがって、クライアント クラスは、有効なイベントを生成する特別な状態リスナー インターフェイスを実装します (イベントは単なるインターフェイスのメソッド呼び出しです)。

このようにして、さまざまなクラスのさまざまな状態のロジックを分離します。現在の状態で状態を内部的に変更して、ライブラリのユーザーがハッキングを行ったり、ライブラリを間違って動作させたりできないようにします。

非同期通信の実装に最適なソリューションだと思います。クライアント側とサーバー側の 2 つのステート マシンを考えてみましょう。

実際にはたくさんのコードなので、概念を示しただけです。

http://en.wikipedia.org/wiki/State_pattern

于 2012-04-19T09:05:18.593 に答える
0

各連絡先には、独自の連絡先リストがあります。

public class Contact
{
  List<Contact> Contacts;
}

各連絡先には独自のイベント (PropertyChanged、LoggedIn など) があります。

public class Contact
{
  List<Contact> Contacts;
  public event OnPropertyChanged;
}

連絡先がログインすると、この連絡先は連絡先リスト内の各連絡先のすべてのイベントに登録されます。

public void LogIn
{
  //Load Contact List for User - Do other stuff
  foreach(Contact c in Contacts)
    c.PropertyChanged += new PropertyChangedEventHandler(ContactPropertyChanged);
}

連絡先リストで何かが発生した場合、ログインしていて、この連絡先がリストにある人がイベントを取得します。

public void ChangeProperty
{
  //Change Property and raise event!
}
于 2012-04-14T12:01:16.290 に答える