2012-07-05 13 views
5

Ho un sacco di business class con autoproperties:Refactor C# proprietà automatiche per campi e proprietà getter/setter?

public class A { 

    public int Id { get; set; } 
    public string Title { get; set;} 

} 

Poiché l'applicazione si evolve, c'è un nuovo requisito per consentire il monitoraggio dei cambiamenti delle proprietà, al fine di inviare al negozio di supporto modificato solo dati.

Al fine di raggiungere questo obiettivo, devo convertire tutte le proprietà di campo + proprietà come questa:

public class A { 

    private int m_Id; 
    public int Id { 
     get { return m_Id; } 
     set { 
      if(m_Id != value){ 
       SetChanged("Id"); 
       m_Id = value; 
      } 
     } 
    } 
    private string m_Title; 
    public string Title 
    { 
     get { return m_Title; } 
     set { 
      if(m_Title != value){ 
       SetChanged("Title"); 
       m_Title = value; 
      } 
     } 
    } 

    protecte void SetChanged(string propertyName) { 
     // Not important here 
    } 
} 

Esiste un modo di refactoring rapidamente il mio codice per evitare di dover modificare manualmente le proprietà?

+3

Se tutte le classi aziendali sono semplicemente classi con autoproprietà e nient'altro, vorrei convertire a utilizzare [modelli T4] (http://www.hanselman.com/blog/T4TextTemplateTransformToolkitCodeGenerationBestKeptVisualStudioSecret.aspx) per generare le classi.Quindi è un cambiamento banale riformattare tutti come sopra. – mellamokb

+5

La sostituzione di Regex può funzionare - anche Resharper ha qualcosa del genere ma probabilmente richiede che tu ne faccia uno a turno. Anche un modello CodeSmith risolverebbe in un batter d'occhio, assumendo che tu sappia come usarlo. Altrimenti creerei uno snippet di codice che ha la struttura giusta e rifare le proprietà. Lo snippet di codice riempirà tutti i bit che suppongo, ma è ancora un lavoro manuale! Andrei per il regex ... o come dice mellamokb, un modello T4, ho avuto un buon successo con loro per cose semplici – Charleh

+0

Usi Resharper? In tal caso, si tratta di una scorciatoia e qualcuno lo ha esteso per aggiungere automaticamente il supporto di INotifyPropertyChanged: https://bitbucket.org/tgmayfield/resharper.tgmcontrib –

risposta

1

Si può sempre e solo di creare un metodo generico che farà l'assegnazione e chiamare SetChange

void SetChangeIfNeeded<T>(ref T field, T value, string propertyName) 
{ 
    if (!EqualityComparer<T>.Default.Equals(field, value)) 
    { 
     field = value; 
     SetChanged(property); 
    } 
} 

Si avrebbe ancora bisogno di avere un campo di nuovo privato. La classe sarebbe simile:

public class A { 

    private int m_id 
    public int Id 
    { 
     get { return m_id }; 
     set { SetChangeIfNeeded<int>(ref m_id, value, "Id"); } 
    } 
} 
+0

Anche se questo semplificherà il codice, sarà comunque necessario aggiornare manualmente tutte le proprietà . –

+0

Ho impostato la risposta come soluzione, perché effettivamente uso questo metodo. Ho, in effetti, fatto alcuni passi: per prima cosa uso CodeRush XPress per rifattorizzare la mia proprietà autopratica su una proprietà con get/set su un backing field. Quindi, ho aggiunto il tuo metodo alla mia classe base. Infine, uso Visual Studio Replace w/Reg ex per estrarre: '_ (\ w +) = value' di' SetValue (ref _ $ 1, value, "$ 1"); '. L'espressione regolare corrisponde a qualsiasi settatore di campo e la sostituisce con la chiamata al metodo. –

+0

Ancora meglio: cerca: 'public ([\ w?] +) (\ W +) {get; impostato; } 'e sostituisci con' public $ 1 $ 2 {get {return m_ $ 2;} set {SetValue (ref m_ $ 2, value, "$ 2");}} private $ 1 m_ $ 2; '. Ciò eviterà la fase di refactoring ed estrarrà automaticamente l'autoprop. –

0

ReSharper può eseguire questa operazione, ma non modifica il setter.

public string Title { 
    get { return m_title; } 
    set { m_title = value; } 
} 
3

Non c'è modo nell'IDE per fare questo, ma se è necessario sostituire tutte le proprietà X, vorrei scrivere una breve un'applicazione console per farlo.

Il processo sarebbe:

  • iterare su tutti i file nella directory corrispondente * cs
  • Foreach di file, espressioni regolari trovare e sostituire vecchia proprietà per la nuova sintassi proprietà

Utilizzando regex per la partita è molto potente. Regex può essere utilizzato in VS2010 per eseguire un'operazione di ricerca/sostituzione. Se si tenta di trovare questo (con regex abilitato)

{(public|private|internal|protected)}:b{[a-zA-Z0-9]+} 
:b{[a-zA-Z0-9]+}:b\{ get; set; \} 

E corrisponderà immobili come questo

public Type Foo { get; set; } 

Nell'applicazione console trovare tutte le righe di codice che corrispondono quanto sopra, quindi avviare dividendoli in Modifier, Tipo, nome proprietà e, infine, sostituire l'intero blocco con qualcosa di simile

// PS: this is pseudocode ;-) or could be your new property template 
private [Type] m_[PropertyName].ToPascaleCase 
public [Type] PropertyName 
{ 
    get { return m_[PropertyName].ToPascaleCase; } 
    set 
    { 
     if(m_[PropertyName].ToPascaleCase != value){ 
      SetChanged([PropertyName]); 
      m_[PropertyName].ToPascaleCase = value; 
     } 
    } 
} 

Infine Auspico, pertanto, di prendere una copia di backup del vostro codice o in esecuzione di questo test fline e test prima di fare il check-in !!

+0

"fare un backup", ++++ 1 :) –

+0

Lol, suona come una cosa stupida da dire ma non sai mai giusto? –

+0

Ho imparato a farlo la prima volta che ho usato Notepad ++ per sostituire tutte le occorrenze di A a B in una soluzione di progetto. :) –

0

Probabilmente non esiste un modo diretto per farlo con la rifrazione. Se questo era il mio problema. Vorrei fare il codice per generare questo:

public string MakePropertyBigger(string varName, string propName, string dataType) 
{ 
    string output = ""; 
    output += string.Format("private {0} {1};", dataType, varName) + Environment.NewLine; 
    output += string.Format("public {0} {1}", dataType, propName) + Environment.NewLine; 
    output += "{" + Environment.NewLine; 
    output += string.Format("get { return {0}; }", varName) + Environment.NewLine; 
    output += string.Format("set { if({0} != value){ SetChanged(\"{1}\");", varName, propName) + Environment.NewLine; 
    output += string.Format("{0} = value; }", varName) + Environment.NewLine; 
    output + "}" + Environment.NewLine + "}"; 

Ora basta collegarlo e farlo uscire.

Problemi correlati