2012-07-05 16 views
5

que tienen un montón de clase de negocios con autoproperties:Refactor C# propiedades automáticas para campos y propiedad getter/setter?

public class A { 

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

} 

Debido a que la aplicación evoluciona, hay un nuevo requisito para permitir el seguimiento de los cambios de las propiedades, con el fin de enviar al almacén de respaldo sólo cambió de datos.

Para alcanzar este objetivo, tengo que convertir todas las propiedades de campo + propiedad como esta:

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

¿Hay una manera de refactorizar mi código rápidamente para evitar tener que cambiar manualmente las propiedades?

+3

Si todas sus clases de negocio son simplemente clases con autopropiedades y nada más, me gustaría convertir el uso de [plantillas T4] (http://www.hanselman.com/blog/T4TextTemplateTransformationToolkitCodeGenerationBestKeptVisualStudioSecret.aspx) para generar sus clases.Entonces es un cambio trivial cambiar el formato de todos ellos como arriba. – mellamokb

+5

Reemplazo de regex puede funcionar - también Resharper tiene algo como esto pero probablemente requiera que haga cada uno por turno. Además, una plantilla de CodeSmith resolvería eso en poco tiempo, suponiendo que sabes cómo usarlo. De lo contrario, crearía un fragmento de código que tiene la estructura correcta y simplemente volvería a hacer las propiedades. ¡El fragmento de código completará todos los bits, supongo, pero sigue siendo un trabajo manual! Me gustaría ir a la expresión regular ... o como dice mellamokb, una plantilla T4, he tenido mucho éxito con ellos para cosas simples – Charleh

+0

¿Usas Resharper? Si es así, se trata de un acceso directo, y alguien lo ha ampliado para agregar automáticamente el soporte INotifyPropertyChanged: https://bitbucket.org/tgmayfield/resharper.tgmcontrib –

Respuesta

1

siempre puede crear un método genérico que va a hacer la tarea y llamar SetChange

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

Usted todavía tiene que tener un campo privado de vuelta. Su clase sería algo como:

public class A { 

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

Aunque esto simplificará el código, aún será necesario actualizar manualmente todas las propiedades . –

+0

He establecido su respuesta como la solución, porque realmente uso este método. De hecho, he realizado algunos pasos: primero uso CodeRush XPress para refactorizar mi propiedad automática a una propiedad con get/set sobre un campo de respaldo. Luego, agregué tu método a mi clase base. Finalmente, uso Visual Studio Replace w/Reg ex para extraer: '_ (\ w +) = value' por' SetValue (ref _ $ 1, value, "$ 1"); '. El regex hace coincidir cualquier setter de campo y lo reemplaza por la llamada a su método. –

+0

Mejor aún: busque: 'public ([\ w?] +) (\ W +) {get; conjunto; } 'y reemplazar por' public $ 1 $ 2 {get {return m_ $ 2;} set {SetValue (ref m_ $ 2, value, "$ 2");}} privado $ 1 m_ $ 2; '. Esto evitará el paso de refactorización y extraerá automáticamente el autoprop. –

0

ReSharper puede hacer esto, pero no modificará setter.

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

No hay manera en el IDE para hacer esto, pero si es necesario sustituir todas las propiedades X, me gustaría escribir una aplicación de consola corta para hacerlo.

El proceso sería:

  • iterar sobre todos los archivos en el directorio encaja * .cs
  • Foreach archivo, expresiones regulares buscar y reemplazar la propiedad viejo por nuevo sintaxis de la propiedad

El uso de expresiones regulares a el partido es muy poderoso. Regex se puede usar en VS2010 para realizar una operación de búsqueda/reemplazo. Si intenta encontrar este (con activar la expresión regular)

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

Emparejará propiedades similares

public Type Foo { get; set; } 

En su aplicación de consola de encontrar todas las líneas de código que coinciden con lo anterior, a continuación, iniciar dividirlos en modificador, Tipo, Nombre y finalmente reemplazar todo el bloque con algo como esto

// 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; 
     } 
    } 
} 

finalmente estaría a favor de tomar una copia de seguridad de su código o correr esta prueba de fline y testing antes de registrarse!

+0

"tomando una copia de seguridad", ++++ 1 :) –

+0

Lol, suena como algo estúpido que decir pero nunca se sabe ¿verdad? –

+0

He aprendido a hacerlo la primera vez que utilicé Notepad ++ para reemplazar todas las apariciones de A a B en una solución de proyecto. :) –

0

Probablemente no haya una manera directa de hacer esto con la refracción. Si este era mi problema Haría código para generar esto:

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 + "}"; 

Ahora simplemente enchúfelo y compórtese.

Cuestiones relacionadas