重构C#自动属性到字段和getter / setter属性?

时间:2012-07-05 15:35:42

标签: c# refactoring

我有一堆带有autoproperties的商务课程:

public class A {

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

}

由于应用程序不断发展,因此需要启用跟踪属性更改的新要求,以便仅向后备存储发送已更改的数据。

为了达到这个目标,我必须将所有属性转换为字段+属性,如下所示:

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

有没有办法快速重构我的代码以避免手动更改属性?

4 个答案:

答案 0 :(得分:3)

在IDE中没有办法做到这一点,但是如果你需要替换所有的X属性,我会编写一个简短的控制台应用程序来完成它。

过程将是:

  • 遍历目录匹配* .cs
  • 中的所有文件
  • Foreach文件,正则表达式查找并替换旧属性以获取新属性语法

使用正则表达式进行匹配非常强大。可以在VS2010中使用Regex进行查找/替换操作。如果你尝试找到这个(启用正则表达式)

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

它将匹配此类属性

public Type Foo { get; set; }

在你的控制台应用程序中找到与上面匹配的所有代码行,然后开始将它们分成修饰符,类型,属性名称,最后用这样的代码替换整个块

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

最后,我建议您在检查之前备份您的代码或离线运行此测试并进行测试!

答案 1 :(得分:1)

您始终可以创建一个通用方法来执行分配并调用SetChange

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

你仍然需要一个私人后场。你的课程看起来像是:

public class A {  

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

答案 2 :(得分:0)

ReSharper可以做到这一点,但不会修改setter。

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

答案 3 :(得分:0)

折射可能没有直接的方法。如果这是我的问题。我会生成代码来生成这个:

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

现在只需将其插入并将其拉出来。

相关问题