将auto属性转换为完整属性

时间:2014-04-29 15:08:49

标签: c# visual-studio properties visual-studio-2013

我经常需要使用支持字段将自动属性转换为完整属性,以便我可以实现INotifyPropertyChanged。当一个班级有50多个属性时,它变得非常繁琐。

public string MyProperty { get; set;}

private string _myProperty;
public string MyProperty
{
    get
    {
        return _myProperty;
    }
    set
    {
        _myProperty = value;
        OnPropertyChanged("MyProperty");
    }
}

我能够创建一个以上述格式创建新属性的代码段,但我不知道是否可以提取现有属性的名称和类型并替换它。

我看到了kindofmagic,但我真的不想在我的项目中使用奥术魔法。

This question解释了如何在Resharper中做到这一点,但我没有Resharper。我甚至下载了试用版,但仍然无法弄清楚如何做到这一点。

有没有办法用代码片段,宏,甚至免费扩展来做到这一点?看起来它应该相当简单。

4 个答案:

答案 0 :(得分:8)

如果你有notepad ++,你可以通过RegEx来做(非常难看,但有效)

找到:(public)\s+([a-zA-z0-9]+)\s+([a-zA-z0-9]+)\s*\{\s*+get;\s*set;\s*\}

替换为:private \2 _\3\; \r\n \1 \2 \3 \r\n \{ \r\n get \{ return _\3\; \} \r\n set \{ _\3=value\; OnPropertyChanged\(\"\3\"\)\; \} \r\n \}

确保选中“正则表达式”

这就是“查找/替换”屏幕的样子: FindReplaceImg

它来自

StartImg

要:

EndImg

编辑:感谢Britton,这是Visual Studio的等价物:

查找:public[^\S\r\n](.+)[^\S\r\n](\b(_\w+|[\w-[0-9_]]\w*)\b)[^\S\r\n]{[^\S\r\n]get;[‌​^\S\r\n]set;[^\S\r\n]}

替换:private $1 _$2;\r\npublic $1 $2 {\r\nget\r\n{\r\nreturn _$2;\r\n}\r\nset\r\n{\r\n_$2 = value; OnPropertyChanged("$2");\r\n}\r\n}

答案 1 :(得分:3)

我最终使用Dan's regex一次转换了许多属性。我还发现了一个名为PropMan的Visual Studio扩展,它适用于一次转换单个属性。只需将光标放在属性上,然后点击Ctrl+\, Ctrl+\即可在auto / full。之间进行转换。

答案 2 :(得分:2)

不幸的是,看起来Visual Studio中不支持这些类型的自定义重构代码段。浏览文档,我发现this

  

SurroundsWith:允许将代码段放在选定的周围   一段代码。

     

扩展:允许在光标处插入代码段。

     

重构:指定在Visual C#期间使用代码段   重构。 重构不能用于自定义代码段。

我还继续创建了一个从头开始创建完整属性的代码段,但它仅适用于新属性,而不是现有属性。

<?xml version="1.0" encoding="utf-8"?>
<CodeSnippets
  xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
  <CodeSnippet Format="1.0.0">
    <Header>
      <Title>fprop</Title>
      <Shortcut>fprop</Shortcut>
      <Description>Full Property with Backing Store</Description>
      <Author>Nathan McGinn</Author>
      <SnippetTypes>
        <SnippetType>Refactoring</SnippetType>
      </SnippetTypes>
    </Header>
    <Snippet>
      <Declarations>
        <Literal>
          <ID>type</ID>
          <Default>string</Default>
          <ToolTip>The type of your property</ToolTip>
        </Literal>
        <Literal>
          <ID>back</ID>
          <Default>_myProperty</Default>
          <ToolTip>The name of your backing variable</ToolTip>
        </Literal>
        <Literal>
          <ID>prop</ID>
          <Default>MyProperty</Default>
          <ToolTip>Your public property's name</ToolTip>
        </Literal>
      </Declarations>
      <Code Language="CSharp">
        <![CDATA[private $type$ $back$;
        public $type$ $prop$
        {
          get
          {
            return this.$back$;
          }
          set
          {
            this.$back$ = value;
            OnPropertyChanged("$prop$");
          }
        }]]>
      </Code>
    </Snippet>
  </CodeSnippet>
</CodeSnippets>

我认为,就片段而言,Visual Studio扩展将需要重构现有代码(或Dan建议的正则表达式查找/替换)。

答案 3 :(得分:1)

我仅使用class1测试了此代码。但是,它会给你起点。我没有使用花哨的命名变量。请根据需要更改变量名称。它会将private...放在属性前面并忽略方法。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
 public class Class1
 {        
    public int Val
    {
        get;
        set;
    }

    public int Val1
    {
        get;
        set;
    }

    public void M1() { }
  }
}

更改上述类的代码

public class Program
{

    public static void Main(string[] args)
    {

        Class1 c = new Class1();
        Type testType = c.GetType();
        PropertyInfo[] prinfo = testType.GetProperties();
        string[] filetest=File.ReadAllLines("Class1.cs"); //put correct file path here
        int index=0,i=0;            
        foreach (PropertyInfo p in prinfo)
        {                
            while(i < filetest.Length )
            {
                index = filetest[i].IndexOf(p.Name);
                if (index > 0)
                {
                    index = 0;
                    filetest[i]=filetest[i].Insert(0, "private " + p.PropertyType.ToString() + " _" + p.Name+";" + Environment.NewLine);
                }
                i++;
            }                  

        }
        File.WriteAllLines("Class1.cs", filetest);//put correct file path here
        Console.Read();
    }        
}