私たちのソフトウェアには、リフレクションを介して動的に見つけられるべきいくつかのクラスがあります。すべてのクラスには、リフレクションコードがオブジェクトをインスタンス化する特定のシグネチャを持つコンストラクターがあります。
ただし、メソッドが参照されているかどうか(Visual Studio Code Lensなどを介して)を確認すると、リフレクションを介した参照はカウントされません。人々はそれらの参照を見逃して、明らかに使用されていないメソッドを削除(または変更)することができます。
リフレクションを介して呼び出されるメソッドをマーク/ドキュメント化するにはどうすればよいですか?
理想的には、メソッドは、同僚とVisual Studio/Roslynおよび他の自動化ツールの両方が、メソッドがリフレクションを介して呼び出されることが意図されていることを「確認」できるようにマークする必要があります。
私たちが使用できる2つのオプションを知っていますが、どちらも十分に満足できるものではありません。 Visual Studioは参照を見つけることができないので:
MyPlugin
を、リフレクターを介して呼び出すコンストラクターを持つクラスにしましょう。呼び出し側のリフレクションコードが、int
パラメーターを受け取るコンストラクターを検索するとします。次のドキュメントは、そのコードlensに、1つの参照を持つコンストラクターを示しています。/// <see cref="MyPlugin.MyPlugin(int)"/> is invoked via reflection
より良いオプションはどれですか?
リフレクションを介して呼び出されることが意図されているメソッド/コンストラクターをマークするためのベストプラクティスは何ですか?
提案されたソリューションの組み合わせ:
<see>
-タグを使用して、コンストラクタ/メソッドの参照カウントを増やします。UsedImplicitlyAttribute
[UsedImplicitly]
は、意図したセマンティクスを正確に持っています。Install-Package JetBrains.Annotations
。SupressMessageAttribute
を使用してメッセージ CA1811: Avoid uncalled private code
。例えば:
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();
}
}
このソリューションでは、コンストラクターの使用目的を、人間の読者と、C#およびVisual Studioで最もよく使用される3つの静的コード分析システムの両方に提供します。
欠点は、コメントと1つまたは2つの注釈の両方が少し冗長に見える可能性があることです。
私は.Netプロジェクトでこの問題を経験したことがありませんが、Javaプロジェクトで同じ問題が定期的に発生します。私の通常のアプローチは、@SuppressWarnings("unused")
アノテーションを使用して理由を説明するコメント(警告を無効にする理由の文書化は私の標準コードスタイルの一部です-コンパイラーが何かを理解できないときはいつでも、人間も苦労している可能性が高いと思います)これには自動的に静的を確保するという利点があります分析ツールは、コードが直接参照することは想定されておらず、人間の読者に詳細な理由を与えることを認識しています。
Javaの@SuppressWarnings
に相当するC#は SuppressMessageAttribute
です。 privateメソッドの場合、メッセージ を使用できますCA1811:呼び出されていないプライベートコードを使用しないでください ;例えば。:
class MyPlugin
{
[System.Diagnostics.CodeAnalysis.SuppressMessage(
"Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode",
Justification = "Constructor is called via reflection")]
private MyPlugin(int arg)
{
throw new NotImplementedException();
}
}
文書化の代替手段は、リフレクション呼び出しが正常に実行されることを確認する単体テストを行うことです。
そうすれば、誰かがメソッドを変更または削除した場合、ビルド/テストプロセスは、何かが壊れていることを警告するはずです。
さて、コードを確認しないと、このようなサウンドは、継承を導入するのに適しています。多分これらのクラスのコンストラクターが呼び出すことができる仮想または抽象メソッドですか?あなたがマークしようとしているメソッドが単なるコンストラクタである場合、あなたは本当にクラスではなくメソッドをマークしようとしていますね?クラスをマークするために過去に私が行ったことの1つは、空のインターフェースを作成することです。次に、コード検査ツールとリファクタリングは、インターフェースを実装するクラスを探すことができます。