1

我有一个有大约 40 个属性的类(我对此没有发言权,它符合规范)。所有属性都有自定义的“设置”方法。

我必须对所有“设置”方法进行一些复杂的验证。我已经将验证分离到一个单独的方法中,让我们调用它

CommonValidate(string PropertyName, string PropertyValue).

到目前为止,我正在从每个单独的“设置”方法中调用此验证方法,如下所示:

    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 个“设置”方法中粘贴了 CommonValidate 方法调用。我发现这非常无效,想象一下是否有更改 CommonValidate 方法中的参数数量的请求。

还有其他方法可以将其更改为更好的模式吗?

4

2 回答 2

1

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

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 是属性所在的类对象。可以在类中执行此操作,也可以将其作为另一个参数传递到函数中。

于 2013-08-13T12:06:36.287 回答
0

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

但是,如果你不走那条路,我会改变的一件事是在 中使用字符串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上面新的代码来获取属性名称键。

于 2013-08-13T12:50:34.397 回答