Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MVVMLight Simple IOC - dynamically register and unregister data service implementations

I have a WPF application with MVVM Light Toolkit support. The application has the following scenario. The application has two Data connection modes. One is WCF service and the other is Direct Database. The application should connect to the Database through one of the above mentioned modes. The connection mode selection is situated in Login window. The end user can select one of the connection modes (WCF Service or Direct Database) and based on that selection a list of connection configurations are loaded in Combo box. (Please check the attached image for more information). The connection configurations are located in a local xml configuration file. Also I have a default connection configuration which should be assigned if any of the connection configurations is selected.

enter image description here

In the View Model Locator, I am registering the default service as follows

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>();

Both DbClient and DataServiceClient implement IDataservice.

If there is already a default connection specified in the configuration file, the above code works fine when the view model locator registers the view models at the application start.ie IDataservice is registered with the default connection configuration.

Now the real issue is when the user selects a connection configuration, that connection configuration becomes the default one and i want the MVVM Light to unregister the previous data service and register the newly selected one, and use it to connect to the data.

I tried the following code in the sign in button click and it failed :(

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
}

Updated Code

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
}
like image 398
Dennis Jose Avatar asked Dec 06 '12 06:12

Dennis Jose


1 Answers

I'd simply remove:

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;
                    }
                }

from your ViewModelLocator and change the code in SignInButtonClick to:

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
}

By doing this you only have to register your service once and you can guarantee that you're registering the correct interface.

like image 151
Faster Solutions Avatar answered Nov 15 '22 19:11

Faster Solutions