Przejdź do treści

Sesje innych użytkowników

Serwer utrzymuje kontekst dla wszystkich zalogowanych sesji użytkowników. Całość jest dobrze izolowana, gdyż na ogół nie powinno się ingerować w sesje innych użytkowników. Niektóre zaawansowane scenariusze wymagają jednak podjęcia takich działań, jak np. odświeżenie danego okna u wszystkich użytkowników. Wychodząc na przeciw tym oczekiwaniom, został do API dodany interfejs pozwalający, na dużą swobodę wyboru adresata (sesji) oraz wykonania dowolnego kodu C# w ramach tej sesji.

RefreshData

W najprostszym scenariuszu potrzebujemy jedynie do innych zalogowanych klientów wysłać informację o tym, że zmieniło się właśnie coś w źródle danych pewnego obiektu biznesowego i w związku z tym należy odświeżyć dane na oknach, które takie dane wyświetlają. W takim wypadku wystarczy użyć metody API.RefreshData() z trzecim parametrem o wartości E.

GetAllLoggedClients

Metoda GUI.GetAllLoggedClients działa nieco inaczej: udostępnia ona kolekcję, zawierającą obiekty zawierające informacje o wszystkich aktywnych sesjach klienckich. Kolekcja jest snapshotem stanu na dany moment i generalnie może się zdarzyć, że jakiś podczas przechodzenia po niej jakiś klient zostanie usunięty, a jakiś inny dojdzie. Dzięki takiej konstrukcji dużo mniejsze jest jednak prawdopodobieństwo, że dostaniemy wtedy błąd związany z modyfikacją kolekcji podczas jej przeglądania. Obiekty w kolekcji nie są bezpośrednio instancjami stanu sesji klienckich, ale pewnymi ich opakowaniami, udostępniającymi interfejs do wygodnego ich przeglądania.

Jeżeli wybierzemy już instancje spełniające żądane kryteria możemy użyć metody Dispatch(), która jako argument przyjmuje metodę. Metoda ta może być anonimowa, bądź może być jedną z metod obiektu. Może też przyjmować parametr (dowolnego typu), który wtedy jest drugim argumentem metody Dispatch(). Metoda przekazywana jako argument do Dispatch() wykonuje się w kontekście instancji klienta określonej przez obiekt na rzecz którego została wykonana. Wszystkie komunikaty które zostaną wygenerowane w odpowiedzi na kod tej metody trafią do innej kolejki komunikatów. W każdym przypadku (poza nieskończoną pętlą wewnątrz), zostanie po jej zakończeniu przywrócona właściwa instancja klienta.

Jakie komunikaty możemy wysyłać do innych sesji? Obiekty kolekcji zwracanej przez omawianą metodę posiadają swoje własne wyliczenie - ActiveObjects. Znajduje się w niej snapshot wszystkich instancji klasy BaseObject, które są aktywne w danej sesji klienta. Tym samym możemy wysyłać komunikaty kierowane do konkretnych instancji klasy BaseObject. Wszystkie metody normalnie dostępne z poziomu metody obiektu biznesowego, po wpisaniu this. są dla nas dostępne.

Przykład 1

Oto jak wygląda implementacja metody RefreshClient(string objectname, string mode) dla parametru mode="E":

if (mode == "E")
{
  foreach (var client in GUI.GetAllLoggedClients())
  {
    foreach (var customObj in client.ActiveObjects.Where(obj => obj.FullObjectName == objectname))
      client.Dispatch(() =>
      {
        customObj.RefreshData();
      });
  }
}

Przykład 2

Kolejny przykład pokazuje jak wywołać dedykowaną metodę konkretnego obiektu biznesowego:

foreach (var client in GUI.GetAllLoggedClients())
{
  foreach (var customObj in client.ActiveObjects.Where(obj => obj.FullObjectName == "WFFA.WFFACOSTINVOICE"))
    client.Dispatch(() =>
    {
      if (customObj is WFFA.WFFACOSTINVOICE)
      {
        WFFA.WFFACOSTINVOICE cost = customObj as WFFA.WFFACOSTINVOICE;
        cost._refsinstate = cost.Calculate_refsinstate();  
      }
    });
}