2012-12-06 15 views
9

Mam aplikację WPF z obsługą MVVM Light Toolkit. Aplikacja ma następujący scenariusz. Aplikacja ma dwa tryby połączenia danych. Jednym z nich jest usługa WCF, a druga to Direct Database. Aplikacja powinna połączyć się z bazą danych za pośrednictwem jednego z wyżej wymienionych trybów. Wybór trybu połączenia znajduje się w oknie logowania. Użytkownik końcowy może wybrać jeden z trybów połączenia (Usługa WCF lub Bezpośrednia baza danych) i na podstawie tego wyboru lista konfiguracji połączeń jest załadowana w polu Kombi. (Sprawdź załączony obraz, aby uzyskać więcej informacji). Konfiguracje połączeń znajdują się w lokalnym pliku konfiguracyjnym XML. Mam także domyślną konfigurację połączenia, która powinna zostać przypisana, jeśli wybrana jest dowolna konfiguracja połączenia.MVVMLight Simple IOC - dynamiczne rejestrowanie i wyrejestrowywanie implementacji usług danych

enter image description here

W widoku modelu Locator, ja rejestracji usługę domyślną następująco

public ViewModelLocator() 
     { 
      ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default); 

      if (ViewModelBase.IsInDesignModeStatic) 
      { 
       // Create design time view services and models 
       if (!SimpleIoc.Default.IsRegistered<IDataService>()) 
        SimpleIoc.Default.Register<IDataService, MockDataClient>(); 
      } 
      else 
      { 
       // Create run time view services and models 
       if (!SimpleIoc.Default.IsRegistered<IDataService>()) 
       { 
        switch (DefaultConnectionConfiguration.ConnectionMode) 
        { 
         case DataConnectionMode.WcfService: 
          var wcfServiceConfiguration = (WcfServiceConfiguration)CurrentConnectionConfiguration; 
          SimpleIoc.Default.Register<IDataService>(
           () => 
           wcfServiceConfiguration != null 
            ? new DataServiceClient("WSHttpBinding_IDataService", 
                   wcfServiceConfiguration.EndpointUrl) 
            : null); 
          break; 

         case DataConnectionMode.Database: 
          SimpleIoc.Default.Register<IDataService, DbClient>(); 
          break; 
        } 
       } 

      } 
     SimpleIoc.Default.Register<LoginViewModel>(); 
     SimpleIoc.Default.Register<ManageConfigurationsViewModel>(); 

Zarówno DbClient i DataServiceClient wdrożenia IDataservice.

Jeśli w pliku konfiguracyjnym jest już określone domyślne połączenie, powyższy kod działa poprawnie, gdy lokalizator modelu widoku rejestruje modele widoku w uruchomieniu aplikacji. IDataservice jest zarejestrowane z domyślną konfiguracją połączenia.

Prawdziwym problemem jest to, że użytkownik wybiera konfigurację połączenia, konfiguracja połączenia staje się domyślna i chcę, aby MVVM Light wyrejestrował poprzednią usługę danych i zarejestrować nowo wybraną, i użył jej do połączenia z dane.

Próbowałem następujący kod w znaku w przycisk i nie udało :(

void SignInButtonClick() 
{ 
     if(SimpleIoc.Default.IsRegistered<IDataService>()) 
            SimpleIoc.Default.Unregister<IDataService>(); 

    switch (DefaultConnectionConfiguration.ConnectionMode) 
          { 
           case DataConnectionMode.WcfService: 
            var wcfServiceConfiguration = (WcfServiceConfiguration)CurrentConnectionConfiguration; 
            SimpleIoc.Default.Register<IDataService>(
             () => 
             wcfServiceConfiguration != null 
              ? new DataServiceClient("WSHttpBinding_IDataService", 
                     wcfServiceConfiguration.EndpointUrl) 
              : null); 
            break; 

           case DataConnectionMode.Database: 
            SimpleIoc.Default.Register<IDataService, DbClient>(); 
            break; 
          } 
//perform authentication process 
} 

zaktualizowany kod

public class ViewModelLocator 
    { 
     public ViewModelLocator() 
     { 
      ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default); 

      if (ViewModelBase.IsInDesignModeStatic) 
      { 
       // Create design time view services and models 
       if (!SimpleIoc.Default.IsRegistered<IDataService>()) 
        SimpleIoc.Default.Register<IDataService, MockDataClient>(); 
      } 
      SimpleIoc.Default.Register<LoginViewModel>(); 
     } 

     public LoginViewModel LoginViewModel 
     { 
      get 
      { 
       return ServiceLocator.Current.GetInstance<LoginViewModel>(); 
      } 
     } 

     public static void Cleanup() 
     { 
      // TODO Clear the ViewModels 
      ServiceLocator.Current.GetInstance<LoginViewModel>().Cleanup(); 
     } 
    } 



public class LoginViewModel : ViewModelBase 
    { 
     ICometDataService service; 

    #region Constructor 
     public LoginViewModel() 
     { 

     } 
     public LoginViewModel(IDataService dataService) 
      : base(dataService) 
     { 
      service = dataService; 
     } 

     #endregion 
} 
+0

Jaka jest różnica między "ICometDataService" a "IDataService" w powyższym kodzie? – tcarvin

+0

@tcarvin - W rzeczywistości jest to IDataService. – Dennis

Odpowiedz

1

bym po prostu usunąć:

if (!SimpleIoc.Default.IsRegistered<IDataService>()) 
       { 
        switch (DefaultConnectionConfiguration.ConnectionMode) 
        { 
         case DataConnectionMode.WcfService: 
          var wcfServiceConfiguration = (WcfServiceConfiguration)CurrentConnectionConfiguration; 
          SimpleIoc.Default.Register<IDataService>(
           () => 
           wcfServiceConfiguration != null 
            ? new DataServiceClient("WSHttpBinding_IDataService", 
                   wcfServiceConfiguration.EndpointUrl) 
            : null); 
          break; 

         case DataConnectionMode.Database: 
          SimpleIoc.Default.Register<IDataService, DbClient>(); 
          break; 
        } 
       } 

z ViewModelLocator i zmień kod w SignInButtonClick na:

void SignInButtonClick() 
{ 

    switch (DefaultConnectionConfiguration.ConnectionMode) 
          { 
           case DataConnectionMode.WcfService: 
            var wcfServiceConfiguration = (WcfServiceConfiguration)CurrentConnectionConfiguration; 
            SimpleIoc.Default.Register<IDataService>(
             () => 
             wcfServiceConfiguration != null 
              ? new DataServiceClient("WSHttpBinding_IDataService", 
                     wcfServiceConfiguration.EndpointUrl) 
              : null); 
            break; 

           case DataConnectionMode.Database: 
            SimpleIoc.Default.Register<IDataService, DbClient>(); 
            break; 
          } 
//perform authentication process 
} 

W ten sposób wystarczy zarejestrować usługę raz i można zagwarantować, że rejestruje się prawidłowy interfejs.

+0

Zrobiłem. Ale wygeneruje błąd podczas tworzenia instancji Log View View Model w ViewModelLocator. Szczegóły wyjątku są następujące: "Wyjątek został zgłoszony przez cel wywołania". Wyjątek wewnętrzny - Typ nie został znaleziony w pamięci podręcznej: DataService.IDataService. " – Dennis

+0

Czy możesz umieścić kod dla swojego modelu widoku logowania? Podejrzewam, że problem może być, że próbujesz wyrejestrować klasę, której obecnie używasz. –

+0

Mój LoginViewModel nie ma żadnego Konstruktora domyślnego.Tak ja dodałem jeden. Następnie wspomniany wyżej wyjątek został usunięty. Obecnie LoginViewModel ma dwa konstruktory Domyślne jeden i sparametryzowany. Podczas rejestracji LoginViewModel (SimpleIoc.Default.Zarejestruj się ();) Mam następujący wyjątek: "Nie można zarejestrować: Wiele konstruktorów znajduje się w LoginViewModel, ale żaden nie jest oznaczony PreferredConstructor.". Dodałem zaktualizowany blok kodu w samym pytaniu. Proszę spojrzeć. – Dennis

Powiązane problemy