Best Practices – Marking Methods Called via Reflection in C#

cdocumentationnetreflection

Our software has several classes that should be dynamically found via reflection. The classes all have a constructor with a specific signature via which the reflection code instantiates objects.
However, when someone checks whether the method is referenced (for example via Visual studio Code Lens), the reference via reflection are not counted. People can miss their references and remove (or change) apparently unused methods.

How should we mark/document methods intended to be called via reflection?

Ideally, the method should be marked in such a way that both colleagues and Visual Studio/Roslyn and other automated tools 'see' that the method is intended to be called via reflection.

I know of two options that we can use but both are not quite satisfying. Since Visual Studio cannot find the references:

  • Use a custom Attribute and mark the constructor with this attribute.
    • A problem is that Attribute properties cannot be a method reference,
      therefore the constructor will still show as having 0 references.
    • Colleagues not familiar with the custom attribute will probably ignore
      it.
    • An advantage of my current approach is the reflection part can use
      the attribute to find the constructor it should call.
  • Use comments to document that a method/constructor is intended to be called via reflection.
    • Automated tools ignore comments (and colleagues might do so as well).
    • Xml Documentation Comments can be used to have Visual Studio count
      an additional reference to the method/constructor:
      Let MyPlugin be the class whose constructor to invoke via reflection.
      Assume the invoking reflection code searches for constructors that take
      an int parameter. The following documentation makes that code lens
      shows the constructor having 1 reference:
      /// <see cref="MyPlugin.MyPlugin(int)"/> is invoked via reflection

Which better options exist?
What is the best-practice for marking a method/constructor that is intended to be called via reflection?

Best Answer

A combination of the suggested solutions:

  • Use XML Documentation tags to document that the constructor/method is called via reflection.
    This should clarify the intended usage to colleagues (and my future self).
  • Use the 'trick' via the <see>-tag to increase the reference count for the constructor/method.
    This makes that code lens and find references show that the constructor/method is referenced.
  • Annotate with Resharper's UsedImplicitlyAttribute
    • Resharper is a de facto standard and [UsedImplicitly] has precisely the intended semantics.
    • Those not using Resharper can install the JetBrains ReSharper Annotations via NuGet:
      PM> Install-Package JetBrains.Annotations.
  • If it is a private method and you are using Visual Studio's code analysis, use SupressMessageAttribute for the message CA1811: Avoid uncalled private code.

For example:

class MyPlugin
{
    /// <remarks>
    /// <see cref="MyPlugin.MyPlugin(int)"/> is called via reflection.
    /// </remarks>
    [JetBrains.Annotations.UsedImplicitly]
    public MyPlugin(int arg)
    {
        throw new NotImplementedException();
    }

    /// <remarks>
    /// <see cref="MyPlugin.MyPlugin(string)"/> is called via reflection.
    /// </remarks>
    [JetBrains.Annotations.UsedImplicitly]
    [System.Diagnostics.CodeAnalysis.SuppressMessage(
        "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode",
        Justification = "Constructor is called via reflection")]
    private MyPlugin(string arg)
    {
        throw new NotImplementedException();
    }
}

The solution confers the intended use of the constructor to both human readers and to the 3 static code analysis systems most used with C# and Visual Studio.
The downside is that both a comment and one or two annotations might seem a bit redundant.

Related Topic