为啥 RelayCommands 通常使用延迟初始化?

Posted

技术标签:

【中文标题】为啥 RelayCommands 通常使用延迟初始化?【英文标题】:Why do RelayCommands typically use lazy initialization?为什么 RelayCommands 通常使用延迟初始化? 【发布时间】:2011-04-15 18:09:50 【问题描述】:

在使用 Josh Smith 的 RelayCommand 时,我见过的大多数示例都使用延迟初始化,例如:

public class ViewModel

    private ICommand myCommand;

    public ICommand MyCommand
    
        get
        
            if (myCommand == null)
            
                myCommand = new RelayCommand(p => DoSomething() );
            

            return myCommand;
        
    
    // ... stuff ...


而不是在构造函数中创建 RelayCommand,像这样:

public class ViewModel

    public ViewModel()
    
            MyCommand = new RelayCommand(p => DoSomething());
    

    public ICommand MyCommand
    
        get;
        private set;

    

    // ... stuff ...

在这里使用延迟初始化有什么好处?在设置绑定时它必须调用 get 属性,所以我看不出有理由使用这个方法而不是在构造函数中进行设置。

我错过了什么吗?

【问题讨论】:

你是对的。 RoutedCommands 的延迟初始化没有任何意义,因为它们非常轻量级,并且一旦 View 绑定到它,它们就会被加载。 【参考方案1】:

实际上,WPF 和 Silverlight 每次绑定只会获取一次中继命令,因此您根本不需要存储支持字段:

public ICommand MyCommand

    get
    
        return new RelayCommand(p => DoSomething());
    

因此,尽管按照您的建议在 .ctor 中创建它并没有错,但几乎没有理由这样做。

【讨论】:

“WPF 和 Silverlight 每次绑定只会获得一次中继命令” -- 我知道在实践中这是真的。但是,鉴于文档没有承诺这种行为,每次检索属性值时创建一个新对象真的是明智之举吗?那天,无论出于何种原因,Microsoft 决定让您的模型对象保留命令对象引用而不是将其缓存在某处更有意义,并且他们每次需要时都从属性中获取值,那一天会发生什么? @Peter Duniho:不仅是微软;我的视图模型一直直接从它自己的方法调用它的命令(和 CanExecute())。所以,不,每次都创建一个新实例是不明智的。 @BoltClock:好点。我将更明确地介绍the other post中的场景 @Peter Duniho:所以我意识到为什么我没有使用字段/属性初始化器——因为我的命令本身也调用视图模型实例方法。当然,我可以将这些初始化移动到构造函数中,尽管我不确定它是否会产生很大的不同。我选择完全不重构。 那是一个可怕的解决方案。您的视图可以多次绑定到同一个命令(可能是主菜单中的一个按钮和上下文菜单中的另一个按钮)。如果您为同一命令创建多个实例,则可能更难调试。

以上是关于为啥 RelayCommands 通常使用延迟初始化?的主要内容,如果未能解决你的问题,请参考以下文章

具有接口的构造函数的StructureMap和延迟初始化

如果没有延迟初始化,回流触发器将无法工作

为啥火花延迟加载比通配符或在数组中传递文件夹慢?

在运行时延迟初始化 Spring Security + 重新加载 Spring Security 配置

项目中用的双重检查锁定是怎么回事

Verilog设计中#,$display,initial为啥不可综合?