Frage

I often need to convert auto properties to full properties with a backing field so that I can implement INotifyPropertyChanged. It gets very tedious when a class has 50+ properties.

public string MyProperty { get; set;}

to

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

I was able to create a code snippet that creates a new property in the above format, but I don't know if it is possible to pull in an existing property's name and type and replace it.

I saw kindofmagic but I really don't want to use arcane magic in my project.

This question explains how to do it in Resharper, but I don't have Resharper. I even downloaded the trial and still couldn't figure out how to do it.

Is there some way to do this with code snippets, macros, or even a free extension? It seems like it should be fairly straightforward.

War es hilfreich?

Lösung

If you have notepad++, you could do it via RegEx (quite ugly, but works)

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

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

Make sure "Regular Expression" is checked

This is what the Find/Replace screen looks like: FindReplaceImg

And it goes from

StartImg

To:

EndImg

Edit: Thanks to Britton, here is the Visual Studio equivalent:

Find: 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]}

Replace: 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}

Andere Tipps

I ended up using Dan's regex for the conversion of many properties at once. I also found a Visual Studio extension called PropMan that is good for converting a single property at a time. Just put the cursor on the property then hit Ctrl+\, Ctrl+\ to convert between auto/full.

Unfortunately, it looks like these type of custom refactoring snippets aren't supported in Visual Studio. Looking through the documentation I found this:

SurroundsWith: allows the code snippet to be placed around a selected piece of code.

Expansion: allows the code snippet to be inserted at the cursor.

Refactoring: specifies that the code snippet is used during Visual C# refactoring. Refactoring cannot be used in custom code snippets.

I also went ahead and created a snippet for creating a full property from scratch, but it's only for new properties, not existing ones.

<?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>

I think that's as far as snippets go, a Visual Studio extension will be required to refactor the existing code (or a regex find/replace as Dan suggested).

I've tested this code with the class1 only. But, it will give you starting point. I've not used fancy naming for the variables. Please change variable names as appropriate. It'll put the private... in front of the properties and ignore the methods.

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

code that change the above class

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();
    }        
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top