我正在编写一个抽象文件解析器(C#),它由两个具体的解析器扩展。两者都需要执行几项检查。目前在抽象解析器中有一个验证方法,它使用反射来调用名称以'test'开头的所有方法。这样添加检查就像添加名称以'test'开头的方法一样简单。
最近我对使用反射有了一些评论,最好使用动态调度。我的问题是,为什么不使用反射,你会如何实现?另外我应该如何使用动态调度来解决这个问题?
public bool Validate()
{
bool combinedResult = true;
Type t = this.GetType();
MethodInfo[] mInfos = t.GetMethods();
foreach (MethodInfo m in mInfos)
{
if (m.Name.StartsWith("Check") && m.IsPublic)
{
combinedResult &= (bool)m.Invoke(this, null);
}
}
return combinedResult;
}
答案 0 :(得分:3)
您应该使用常规OOP而不是反射。您是否抽象类公开了一个像Validate这样的抽象方法。每个解析器都必须实现它。在Validate中,每个解析器都会调用虔诚的Check方法来完成工作。
答案 1 :(得分:2)
代码工作没有任何问题......直到有人来维护它。特别是,这种惯例需要非常仔细地记录下来,因为你的班级将如何做它的作用并不是很明显。
(顺便说一句,然而,使用Reflection会相当慢。)
最明显的方法可能是使用由子类实现的抽象基本方法bool Validate()
。然后子类具有例如
public override bool Validate()
{
return TestFirst() &&
TestSecond() &&
TestThird();
}
虽然这看起来很笨重但是很明显发生了什么。它还使Validate()
的单元测试变得轻而易举。
也许可以让Testxxx()
方法在构造函数中使用超类注册它们,这样它们就会被自动调用 - 但这样做的工作量更大,而且维护性更差。
如果确实希望使用反射执行此操作,请考虑使用属性标记Testxxx()
方法并反映这些方法。然后你的代码仍然可读。
答案 2 :(得分:0)
据我所知,动态调度适用于需要根据参数类型确定调用方法的情况。在你的情况下,你调用没有参数的方法,所以我不确定动态调度与此有什么关系。
我喜欢你快速而肮脏的方法。对于生产质量代码,我发现您的方法存在以下潜在问题:
string CheckWithWrongReturnType
,那么您的代码会中断。为了避免反射,我会创建一个委托,并让每个类返回一个委托列表。
delegate bool Validator();
bool F1() { return true; }
bool F2() { return false; }
List<Validator> validators = new List<Validator>(F1, F2);
//然后在主类中你可以这样做:
foreach(Validator v in validators)
{
combinedResult &= v();
}