MVVM share object between the all the views

2019-07-18 15:01发布

I have MVVM Project and I want to share one object( singleton ) from the model between several viewmodel what is the good practice to do that? Thank you for the help

4条回答
老娘就宠你
2楼-- · 2019-07-18 15:35

I would suggest that you inject the dependency into each view model (either constructor or property injection for example), and always work against abstractions in your view models, so that your dependency can easily be mocked or replaced as required. You then just need to ensure that each view model uses the same instance of your type - if you are using an IoC container, you can register a shared instance of your type easily.

查看更多
对你真心纯属浪费
3楼-- · 2019-07-18 15:39

If you have control over all viewmodels then an easy approach (that I've used personally) is to just put a static variable on the base class of all viewmodels and make that accessible to all inheritors (either protected or even public if its useful outside of the viewmodels).

It's good practice anyway to have a common base class for your viewmodels since it allows you to implement property notification in one place (and other common functionality, like messaging etc.) instead of replicating it in all viewmodels.

Something like this is what I've used in my projects:

public class MyViewModelBase : INotifyPropertyChanged
{
    private static MySharedSingleton _sharedObj;
    static MyViewModelBase()
    {
        _sharedObj = new MySharedSingleton(/* initialize it here if needed */);
    }
    // or public
    protected MySharedSingleton SharedObject { get { return _sharedObj; } }

    // INotifyPropertyChanged stuff
    // ...
}

public class SomeViewModel : MyViewModelBase
{
    void SomeMethod()
    {
        SharedObject.DoStuff();
    }
}

If the construction of the shared singleton object is heavy, you can of course use any of the standard techniques for lazy instantiation of it.

查看更多
趁早两清
4楼-- · 2019-07-18 15:43

If the object is needed and does not provide value without it force the interface within the object via Constructor Injection; do not push a concrete type via injection always make use of an interface.

Since you are not making use of an IoC container such as Unity, you will need to create your singleton instance at the startup of your application and then make sure that the given instance is passed in via the given ViewModels constructor as needed.

A better approach would be pushing the singleton instance to a service which can provide the needed behavior and then disregard pushing the singleton into the Model. This would be a more MVVM purist approach and will separate concerns across your Models/ViewModels.

EDIT:

If you were making use of Unity you would define a Lifetime Manager at the time of registration.

// Register a type to have a singleton lifetime without mapping the type
// Uses the container only to implement singleton behavior
myContainer.RegisterType<MySingletonObject>(new ContainerControlledLifetimeManager());
// Following code will return a singleton instance of MySingletonObject
// Container will take over lifetime management of the object
myContainer.Resolve<MySingletonObject>();

Once you do this any attempt to resolve MySingletonObject via the IUnityContainer would resolve to the same instance providing the singleton behavior you so desire across the application. ViewModels themselves should not need to have the same instance returned. The data it needs should be abstracted away via a service as referenced earlier which could potentially behave like a singleton and provide a stateful implementation if needed but the ViewModel should not need to be a singleton. If you find yourself making either a Model or ViewModel a singleton; take a step back and analyze your design.

查看更多
SAY GOODBYE
5楼-- · 2019-07-18 15:47

I use a separate class for my global singleton with a model. This relieves me of agonizing over how to inject this model into view models and other models. E.g.

The singleton:

public class ApplicationModel
{
    public string LoggedOnUser { get; set; }
    // Etc.

    private ApplicationModel() {
        // Set things up.
    }

    private static ApplicationModel _active;
    public static ApplicationModel Current {
        get {
            if (_active == null) {
                _active = new ApplicationModel();
            }
            return _active;
        }
    }
}

The view model that needs to hold no reference to the singleton:

public class SomeViewModel
{
    private string _user;
    public SomeViewModel() {
        _user = ApplicationModel.Current.LoggedOnUser;
    }
}
查看更多
登录 后发表回答