Resharper 为 ReactiveUI 的 ReactiveObject 创建自定义重构

Posted

技术标签:

【中文标题】Resharper 为 ReactiveUI 的 ReactiveObject 创建自定义重构【英文标题】:Resharper Create Custom Refactor for ReactiveUI's ReactiveObject 【发布时间】:2013-10-06 17:23:11 【问题描述】:

所以我的代码中有大量视图模型和模型,它们要求每个属性都使用 ReactiveUI 方式来观察它们的变化:

private bool _myProperty;
public Boolean MyProperty

    get  return _myProperty; 
    set  this.RaiseAndSetIfChanged(ref _myProperty, value); 

使用 Resharper 我可以转换:

public Boolean MyProperty  get; set; 

进入这个:

private bool _myProperty;
public Boolean MyProperty

    get  return _myProperty; 
    set  _myProperty = value; 

然后我必须手动将其转换为上面的第一个代码 sn-p 以合并我的 ReactiveUI 功能。

我想弄清楚的是,是否有一种方法可以为 Resharper 编写自定义重构,这将允许我在光标位于顶部时出现的工具菜单中添加“转换为反应性属性”快捷方式一个简单的属性成员? (在已经存在的“转换为自动属性”和“转换为带有更改通知的属性”选项之上。

非常感谢任何帮助!这将在编码时为我节省大量时间......

【问题讨论】:

【参考方案1】:

我自己从未尝试过,但我一直想自己编写一个 R# 模板。根据这个post,这对你有用吗?

private $Type$ $BackingField$;
public $Type$ $Property$

  get
  
    return this.$BackingField$;
  
  set
  
    this.RaiseAndSetIfPropertyChanged(ref $BackingField$, value); 
  

【讨论】:

有趣...实际上不是一条糟糕的路线。我实际上是想弄清楚如何将其添加为重构,但我不介意将其用作模板...唯一的问题是这仅适用于新代码,而不适用于需要修改的现有属性。 ..如果我没有得到任何关于将其创建为重构的回复,尽管我会将其标记为答案【参考方案2】:

开箱即用,ReSharper 支持 ReactiveUI 的 ReactiveUI.raisePropertyChanged(string) 重载,以将自动属性转换为具有更改调用的属性,即:

转这个:

进入这个:

这是由 ReSharper 7 中引入的 ReSharper 的 support for INotifyPropertyChanged 完成的。它的工作方式是 ReactiveUI.raisePropertyChanged(string) 方法使用 ReSharper 的 Annotation 属性(称为 [NotifyPropertyChangedInvocator])进行修饰。当使用特定签名装饰方法时,实现INotifyPropertyChanged 接口的类型上的此属性将自动允许 ReSharper 将其用作“更改通知”重构。

在您的情况下,使用相对较少的代码,您可以使用相同的机制。但是,您的 RaiseAndSetIfPropertyChanged 方法需要具有特定的签名。您可以做的是,创建一个派生自 ReactiveObject 的抽象类,并在那里实现您的方法:

public abstract class ReactiveObjectBase : ReactiveObject

    [NotifyPropertyChangedInvocator]
    protected void RaiseAndSetIfPropertyChanged<T>(ref T obj, T value, string propertyName)
    
        // call real raise method here
    

这个方法需要有这个确切的签名(方法名称可能不同),并且必须用NotifyPropertyChangedInvocator 属性修饰。

之后,只需将视图模型的基本类型更改为ReactiveObjectBase,现在您就可以将自动属性转换为更改通知:

希望这会有所帮助!

【讨论】:

Hmmmm...这似乎很有希望,尽管我不确定我是否需要实现任何东西。通常,当您使用该快捷方式时,resharper 会将 notifyproperrtychangedinvocator 注释方法添加到类中,但对于从 ReactiveObject 扩展的类似乎没有这样做。作为说明,我的问题中有一个错字,调用的方法是“RaiseAndSetIfChanged”(可直接从 ReactiveUI 获得),所以正如我所看到的,正如你所说的那样,它支持来自 ReactiveUI 的 raisePropertyChanged 重载我认为这已经是我想要的设置了,哈哈。 是的,看看 GitHub 上的 ReactiveUI 代码,RaiseAndSetIfChanged 方法似乎只是调用 raisePropertyChanged 方法......除了它还在进行更改之前调用 raisePropertyChanging 方法(我没有不相信会影响我)...已选择答案! 我的基类中有 OnPropChanged 和 SetProperty 方法,这两个方法都归于 NotifyPropertyChangedInvocator。我从 OnPropChanged 中删除了该属性,并且这两个选项都从重构上下文菜单中消失了。可能对某人来说是个问题......

以上是关于Resharper 为 ReactiveUI 的 ReactiveObject 创建自定义重构的主要内容,如果未能解决你的问题,请参考以下文章

ReactiveUI:如何实现定期刷新的ReactiveList

如何在 Avalonia.ReactiveUI 中使用 Autofac 作为 DI 容器?

我应该如何使用 Avalonia(ReactiveUI) 控制命令的可执行性?

ReactiveUI 是不是提供类似 PRISM ViewModelLocator 的服务?

ReactiveUI 中的 Xamarin.Forms 控件是不是需要自定义绑定?

无法将 ReactiveUI 添加到 NUnit 测试项目