DanP
DanP

Reputation: 6478

Performing an audit using reflection

I would like to perform an audit as part of a unit test that uses reflection to verify some assumptions, the basic-psuedo code for this would be as follows:

  1. For each class in a given assembly, locate the controller classes (ASP.NET MVC2).

  2. For each action in this class, locate any that are decorated with a given attribute (lets call this TargetAttribute)

  3. For each of these methods decorated with the attribute of interest, ensure that at least one of the action method's parameters implements a given interface (let's call this ITarget).

How would I go about performing such a check? (answers in C# or VB.NET are welcome)

Edit:

I am posting the final code here (translated to VB.NET) that performs this check:

    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

Upvotes: 2

Views: 478

Answers (2)

Mitch Humeniuk
Mitch Humeniuk

Reputation: 1

Your auditing is a lot of trouble for a unit test that will probably not help with code quality. MVC is supposed to be better for unit testing but unit tests are not helpful. Web Forms is much better at everything else besides unit testing, so it is a better choice for enterprise applications.

Upvotes: 0

BeRecursive
BeRecursive

Reputation: 6376

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;
}

Upvotes: 2

Related Questions