Search code examples
c#oopreflectiondynamic-dispatch

Reflection or Dynamic Dispatching


I'm writing a abstract file parser (C#) which is extended by two concrete parsers. Both need to perform several checks. Currently there is a validate method in the abstract parser, which uses reflection to call all methods with a name starting with 'test'. That way adding checks is as easy as adding a method with a name that starts with 'test'.

Now recently I've had some comments about the use of reflection and it being better to use dynamic dispatching. My question to you is, why not use reflection and how would you implement this? Also how should I use dynamic dispatch to solve this problem?

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

Solution

  • As far as I understand, dynamic dispatch is for the cases when you need to determine the method to call based on the type of its arguments. In your case, you call methods with no arguments, so I am not sure what dynamic dispatch has to do with this.

    I like your approach for quick-and-dirty stuff. For production-quality code, I see the following potential problems with your approach:

    • you don't check for argument types and return types, so if you or someone adds a method string CheckWithWrongReturnType then your code breaks.
    • every time you call this function it calls GetMethods() and goes through the list. This is probably inefficient. Might be better to cache this list in an array.

    To avoid reflection, I would create a delegate and make each class return a list of delegates.

    delegate bool Validator();
    
    bool F1() { return true;  }
    bool F2() { return false; }
    
    List<Validator> validators = new List<Validator>(F1, F2);
    

    // then in the main class you can do this:

    foreach(Validator v in validators)
    {
       combinedResult &= v();
    }