我有一个有大约40个属性的类(我没有说这个,它是按照规范)。所有属性都有自定义“设置”方法。
我必须对所有“set”方法强加一点复杂的验证。我已经将验证分成了一个单独的方法,让我们调用它
CommonValidate(string PropertyName, string PropertyValue)
。
截至目前,我正在从每个“set”方法中调用此验证方法,如下所示:
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方法中的参数数量有变更请求。
还有其他方法可以将其更改为更好的模式吗?
答案 0 :(得分: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是属性所在的类对象。可以在类中执行此操作,也可以将其作为另一个参数传递给函数。
答案 1 :(得分: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())
}
然后,setter看起来像
public string Property1
{
set
{
this.field1 = value;
CommonValidate(c => c.Property1, value);
}
}
这样做的好处是,如果更改类上属性的名称,则编译时错误不会更改CommonValidate
调用。如果你选择了这条路线,你应该使用类似的东西设置你的验证:我假设你有一个构造函数在某处填充Dictionary<string, Func<string, bool>
- 使用类似于新CommonValidate
的代码以上获取属性名称键。