2012-05-04 20 views
8

Buduję aplikację MVC3 przy użyciu szkieletu Ninject. Mam usługę, która jest czasochłonna do zainicjowania, a na koniec ta usługa będzie zawierała obiekt zawierający informacje specyficzne dla użytkownika, wtedy muszę ponownie użyć tej usługi, o ile sesja użytkownika jest aktywna, tak aby można uniknąć ponownie zainicjować tę usługę i ponownieKoncepcja zakresu sesji przedmiotu w MVC3

więc moje pytanie jest

Kiedy wiążę usługę korzystając Ninject jaki zakres powinien wybrać, nie ma sesji za zakresu w Ninject, więc jaki jest najlepszy sposób na wdrożenie tego wymogu? czy w ogóle poszedłem w złym kierunku?

Utworzyłem niestandardowego dostawcę dla jednej z moich usług, która utworzy usługę opartą na szczegółach dotyczących nazwy użytkownika, która jest pobierana z bieżącego pliku Controller.User.Identity.Name. Poniższy kod nie będzie działał, ponieważ brakuje zmiennej lokalnej nazwa_użytkownika, w jaki sposób mogę przekazać wartość nazwy użytkownika do mojego dostawcy niestandardowego przez program Ninject, aby móc ją pobrać z IContext?

public class TfsConnectionManagerProvider : Provider<TfsConnectionManager> 
    { 
     protected override TfsConnectionManager CreateInstance(IContext context) 
     { 
      Uri serverUri = new Uri(ConfigurationHelper.TfsServerUrl); 
      // Connect to the server without impersonation 
      using (TfsTeamProjectCollection baseUserConnection = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(serverUri)) 
      { 
       // Get the identity management service 
       IIdentityManagementService ims = baseUserConnection.GetService<IIdentityManagementService>(); 

       // Get the identity to impersonate 
       TeamFoundationIdentity identity = ims.ReadIdentity 
       (
        IdentitySearchFactor.AccountName, 
        userName, //NOTE: How can I get user name value from IContext??? 
        MembershipQuery.None, 
        ReadIdentityOptions.None 
       ); 

       // Connect using the impersonated identity 
       using (TfsTeamProjectCollection impersonatedConnection = new TfsTeamProjectCollection(serverUri, identity.Descriptor)) 
       { 
        WorkItemStore store = impersonatedConnection.GetService<WorkItemStore>(); 

        return new TfsConnectionManager 
        { 
         Store = store 
        }; 
       } 
      } 
     } 
    } 
+0

Zobacz też http: // stackoverflow.com/questions/4687707/ninject-per-session-singleton –

Odpowiedz

2

Okazało się, że korzystam z dostawcy niestandardowego do tworzenia instancji i sprawdzanego przez dostawcę niestandardowego, czy istnieje w sesji, czy nie.

Wiązanie odbywa się w następujący sposób

Bind<IRepository>().ToProvider(new TfsRepositoryProvider()); 

Zwyczaj Provider jest poniżej

public class TfsRepositoryProvider : Provider<TfsRepository> 
    { 
     private const string SesTfsRepository = "SES_TFS_REPOSITORY"; 

     protected override TfsRepository CreateInstance(IContext context) 
     { 
      // Retrieve services from kernel 
      HttpContextBase httpContext = context.Kernel.Get<HttpContextBase>(); 

      if (httpContext == null || httpContext.Session == null) 
      { 
       throw new Exception("No bind service found in Kernel for HttpContextBase"); 
      } 

      return (httpContext.Session[SesTfsRepository] ?? (
        httpContext.Session[SesTfsRepository] = new TfsRepository(context.Kernel.Get<IWorkItemStoreWrapper>())) 
       ) as TfsRepository; 
     } 
    } 
0

Ok, można buforować/przechowywać informacje użytkownika w aplikacji i tylko zadzwonić do usługi zewnętrznej, jeśli nie masz (aktualne) informacje o użytkowniku. W "warstwie" pobierania informacji użytkownika, po prostu zaprogramujesz te dwie możliwości.

Miejsce przechowywania w pamięci podręcznej zależy wyłącznie od Ciebie. Możesz przechowywać te informacje na przykład w lokalnej bazie danych.

Najwyraźniej zrozumiałem, że się mylę, moje przeprosiny (poniżej mojej oryginalnej odpowiedzi).

można użyć na przykład (streszczenie) fabrykę, która posiada statyczny członek usługi (na przykład), więc zostanie on ponownie wykorzystane.

Chociaż w zależności od usługi, to może mieć jakieś skutki niepożądanych (zrobiłem to raz z usług danych i w ASP.NET MVC3 aplikacji kontekście moich danych została trochę przykręcony z powodu jakiejś magii, która stało). Wszystko, co chcę powiedzieć, to: bądź ostrożny i sprawdź to dobrze.

+0

Przepraszam, mogę nie wyjaśnić dobrze mojego pytania, inicjalizacja usługi obejmuje połączenia z niektórymi usługami sieciowymi, które następnie zwrócą informacje specyficzne dla użytkownika. Nie mogę zrobić tego statycznie, ponieważ jest to specyficzne dla użytkownika. – Ming

+0

Ow, to źle cię zrozumiałem :). Możesz zrobić próbę buforowania danych użytkownika (informacji) w aplikacji i nawiązywać połączenia tylko z usługami zewnętrznymi, jeśli nie masz informacji o sobie. – Styxxy

+0

Tak, więc to przychodzi do mojego prawdziwego pytania powyżej - jak mogę to osiągnąć przez powiązanie Ninject przy użyciu zakresu – Ming

7

Zakres sesji celowo nie jest oferowany w programie Ninject, ponieważ usługi w stanie sesji są nieprawidłowe w prawie każdej sytuacji. Powinieneś bardzo uważnie używać stanu sesji, ponieważ przynosi on wiele wad.

Spróbuj mieć aplikację bezstanową na pierwszym miejscu.

Jeśli istnieje uzasadniony powód posiadania danych w zakresie sesji, należy umieścić te dane (nie usługi) w stanie sesji i korzystać z usług, które są w trybie pojedynczej, przejściowej lub zakres żądania dla przetwarzania (rozdzielenie danych i funkcjonalności).

+0

Dzięki Remo, może być mylące, że umieszczam sesję w moim oryginalnym opisie. Nie mam na myśli, że zamierzałem użyć sesji do przechowywania danych, celem jest ponowne wykorzystanie specyficznego dla użytkownika obiektu, który powrócił z długotrwałej usługi, jak to tylko możliwe w ramach struktury Ninject. Każdy odpowiedni pomysł na projekt zostanie przyjęty z zadowoleniem – Ming