MVVM在所有视图之间共享对象

时间:2010-12-26 21:57:08

标签: mvvm singleton

我有MVVM项目,我想在几个viewmodel之间从模型共享一个对象(singleton),这样做的好习惯是什么? 谢谢你的帮助

4 个答案:

答案 0 :(得分:3)

如果对象是必需的并且没有提供价值而没有它通过Constructor Injection强制对象内的界面;不要通过注射推动混凝土类型总是使用接口。

由于您没有使用Unity之类的IoC容器,因此您需要在应用程序启动时创建单例实例,然后确保通过给定的ViewModel传入给定的实例构造函数根据需要。

更好的方法是将单例实例推送到可以提供所需行为的服务,然后忽略将单例推入模型。这将是一个更MVVM纯粹的方法,并将分离您的Models / ViewModels中的问题。

编辑:

如果您正在使用Unity,则在注册时定义Lifetime Manager

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

执行此操作后,任何通过MySingletonObject解析IUnityContainer的尝试都将解析为同一实例,提供您在整个应用程序中所需的单例行为。 ViewModels本身不需要返回相同的实例。它所需的数据应该通过之前引用的服务抽象出来,这可能表现得像一个单例,并在需要时提供有状态实现,但ViewModel不需要是单例。如果您发现自己制作模型或ViewModel是单身人士;退后一步,分析你的设计。

答案 1 :(得分:2)

如果您可以控制所有视图模型,那么一种简单的方法(我个人使用过)就是在所有视图模型的基类上放置一个静态变量,并使所有继承者都可以访问它(受保护的,甚至是公共的)它在视图模型之外很有用。)

无论如何,为视图模型建立一个公共基类是很好的做法,因为它允许您在一个地方实现属性通知(以及其他常见功能,如消息传递等),而不是在所有视图模型中复制它。

这样的东西就是我在项目中使用的东西:

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

如果共享单例对象的构造很重,您当然可以使用它的任何standard techniques for lazy instantiation

答案 2 :(得分:1)

我建议您将依赖项注入每个视图模型(例如构造函数或属性注入),并始终对视图模型中的抽象进行处理,以便可以根据需要轻松地模拟或替换依赖项。然后,您只需确保每个视图模型使用相同的类型实例 - 如果您使用的是IoC容器,则可以轻松注册类型的共享实例。

答案 3 :(得分:0)

我使用单独的类作为我的全局单例和模型。这使我对如何将此模型注入视图模型和其他模型感到痛苦。 E.g。

单身人士:

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

视图模型不需要引用单例:

public class SomeViewModel
{
    private string _user;
    public SomeViewModel() {
        _user = ApplicationModel.Current.LoggedOnUser;
    }
}