将 C# 自动属性重构为字段和 getter/setter 属性



我有一堆带有自动属性的商务类:

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

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

IDE 中没有办法执行此操作,但是如果您需要替换所有 X 属性,我会编写一个简短的控制台应用程序来执行此操作。

该过程将是:

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

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

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

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

您始终可以只创建一个泛型方法,该方法将执行赋值并调用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"); }
    }  
}  

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

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

可能没有直接的方法可以通过折射来做到这一点。如果这是我的问题。我会编写代码来生成这个:

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

现在只需将其插入并取出即可。

最新更新