2010-11-11 79 views
2

执行审计我想执行审核作为使用反射来验证一些假设一个单元测试的一部分,这种情况的基本-伪代码将如下所示:使用反射

  1. 对于每个在给定程序集中的类 找到控制器类 (ASP.NET MVC2)。

  2. 对于这个类中的每个动作, 找到任何饰有 给定的属性(可以称之为 TargetAttribute

  3. 对于每一种方法装饰 与感兴趣的属性, 保证至少有一个动作方法的参数实现了给定的 接口(我们称之为 ITarget)。

我该如何去执行这样的检查? (C#或VB.NET的答案是欢迎)

编辑:

我在这里张贴的最终代码(翻译成VB.NET)执行此检查:

Dim ass As Assembly = Assembly.GetAssembly(GetType(Web.WebConfiguratorMarker)) 

    Dim methodsToCheck = ass.GetTypes(). 
         Where(Function(t) t.IsSubclassOf(GetType(Controller))). 
         SelectMany(Function(t) t.GetMethods()). 
         Where(Function(m) m.GetCustomAttributes(GetType(AutoValidateJsonModelAttribute), False).Length > 0). 
         Where(Function(m) m.ReturnType Is GetType(ActionResult)).ToArray() 

    For Each method In methodsToCheck 

     Dim implementsIValidatable As Boolean = False 

     For Each param In method.GetParameters() 
      If GetType(IValidatable).IsAssignableFrom(param.ParameterType) Then 
       implementsIValidatable = True 
       Exit For 
      End If 
     Next 

     Assert.True(implementsIValidatable, String.Format("Controller of type [{0}] has an action [{1}] that is decorated with <AutoValidateJsonModel()> but does not have a IValidatable instance as a param", method.DeclaringType, method.Name)) 

    Next 

回答

2
var assembly = System.Reflection.Assembly.GetExecutingAssembly(); 

var methods = assembly.GetTypes() 
       .Where(t => t is System.Web.Mvc.Controller) 
       .SelectMany(t => t.GetMethods()) 
       .Where(m => m.ReturnType is ActionResult) 
       .Where(m => m.GetCustomAttributes(typeof(TargetAttribute), false).Length > 0) 
       .ToArray(); 

bool implementsITarget = false; 

foreach(method in methods) 
{ 
    foreach(param in method.GetParameters()) 
    { 
     if(param.ParameterType is ITarget) 
     { 
      implementsITarget = true; 
      break; 
     } 
    } 
    Assert.True(implementsITarget , String.Format("Controller {0} has action {1} that does not implement ITarget but is decorated with TargetAttribute", method.DeclaringType, method.Name)); 
    implementsITarget = false; 
} 
+0

这看起来很有前途,谢谢!一些事情:我认为通过检查基类可以更好地完成控制器检查,不是吗?例如。应该从基类控制器类继承...另外,我不确定我想忽略抽象类型,因为我使用控制器的继承...除了这些小细节之外,这看起来像一个很好的解决方案。 – DanP 2010-11-11 13:30:21

+0

@DanP:好的,做了一些反映你的建议的改变。你完全正确的控制器名称检查,这是我懒惰:P – BeRecursive 2010-11-11 13:35:31

+0

这几乎正是我所需要的...唯一明显的错误是比较param是ITarget ...你会想要param.ParameterType是ITarget - 很好的答案! – DanP 2010-11-11 20:07:41

0

您的审计对于单元测试来说很麻烦,这可能无助于代码质量。 MVC应该是更好的单元测试,但单元测试没有帮助。除了单元测试之外,Web Forms在其他所有方面都要好得多,所以它对于企业应用程序来说是更好的选择。

+0

一致认为,这更多的是“公约测试”;将它作为单元测试套件的一部分包含在内是非常有用的,这样,如果作为CI过程的一部分,构建将失败。 – DanP 2010-11-16 15:21:00