如何重写此代码块

本文关键字:代码 重写 何重写 | 更新日期: 2023-09-27 18:27:25

我有一个类有大约40个属性(我对此没有发言权,这是根据规范)。所有属性都有自定义的"set"方法。

有一个有点复杂的验证,我必须把它强加给所有的"集合"方法。我已经将验证分离为一个单独的方法,我们称之为

CCD_ 1。

到目前为止,我从每个单独的"集合"方法中调用这个验证方法,如下所示:

    public string Property1
    {
        set 
        { 
           this.field1 = value; 
           CommonValidate(Property1, this.field1);
        }
     }
    public DateTime Property2
    {
        set 
        { 
           this.field2 = value.ToString("ddMMyy");; 
           CommonValidate(Property2, this.field2);
        }
     }
     public string Property3
    {
        set 
        { 
           this.field3 = value; 
           CommonValidate(Property3, this.field3);
        }
     }

通过这种方式,我刚刚在所有40个"set"方法中粘贴了CommonValidate方法调用。我发现这是非常无效的,想象一下,如果有对CommonValidate方法中参数数量的更改请求。

有没有其他方法可以把它改成更好的模式?

如何重写此代码块

您可以使用反射来获得一个函数,该函数以属性和新值的名称传递。它进行验证,然后使用值执行正常设置。反射在速度方面效率不高,但对重用代码非常有用。进行一些诊断,以确保损失的时间在您可接受的范围内。

void ValidateAndSet(string propName, object newValue){
    foreach(var prop in propsClass.GetType().GetProperties().Where(p => p.Name == propName))
    {
        if(CommonValidate(prop, newValue))
            prop.GetSetMethod().Invoke(propsClass, new object[] { newValue});
        return; // Only one anyways
    }
    Logger.Log("Failed to find the property '{0}' to set '{1}'", propName, newValue);
}

propsClass是属性所在的类对象。可以在类中执行此操作,也可以将其作为另一个参数在函数中传递。

有人已经提到了动态类,我不熟悉它们,但简短的阅读会让它们听起来对您的问题很有吸引力。

然而,如果您不走这条路,我会改变的一件事是在CommonValidate中使用字符串,而使用System.Linq.Expression

我会把它重写成这样:

static void CommonValidate<T>(Expression<Func<MyClass, T>> propertySelector, T newValue) //replace MyClass with name of current class
{
    MemberExpression memberExpression = propertySelector.Body as MemberExpression;
    if (memberExpression == null)
        throw new ArgumentException("propertySelector")
    string propertyName = MemberExpression.Member.Name;
    //validation code, e.g.
    CommonValidate(propertyName, newValue.ToString())
}

然后二传手会看起来像

public string Property1
{
    set 
    { 
       this.field1 = value; 
       CommonValidate(c => c.Property1, value);
    }
 }

这样做的好处是,如果更改类上属性的名称,则不更改CommonValidate调用将成为编译时错误。如果你真的走了这条路,你应该使用类似的东西来设置你的验证:我假设你在某个地方有一个构造函数来填充Dictionary<string, Func<string, bool>——使用类似于上面新的CommonValidate中的代码来获取属性名称键。