3

2 つの具象パーサーによって拡張された抽象ファイル パーサー (C#) を作成しています。どちらもいくつかのチェックを実行する必要があります。現在、抽象パーサーには検証メソッドがあり、リフレクションを使用して「test」で始まる名前のすべてのメソッドを呼び出します。そうすれば、「test」で始まる名前のメソッドを追加するのと同じくらい簡単にチェックを追加できます。

最近、リフレクションの使用と、動的ディスパッチを使用する方が良いというコメントがありました。あなたへの私の質問は、リフレクションを使用しない理由と、これをどのように実装するかということです。また、動的ディスパッチを使用してこの問題を解決するにはどうすればよいですか?

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

3 に答える 3

3

これには、リフレクションではなく、通常の OOP を使用する必要があります。Validate のような抽象メソッドを公開するクラスを抽象化します。各パーサーはそれを実装する必要があります。Validate では、各パーサーが敬虔な Check メソッドを呼び出して作業を行います。

于 2009-11-30T11:15:00.120 に答える
2

機能するコードに問題はありません...誰かがそれを維持するまで。特に、この種の規則は、クラスが何をするかがすぐにはわからないため、非常に注意深く文書化する必要があります。

(余談ですが、これに Reflection を使用するとかなり遅くなります。)

最も明白な方法はbool Validate()、サブクラスによって実装される抽象基本メソッドを持つことです。サブクラスには、例えば

public override bool Validate()
{
    return TestFirst() && 
        TestSecond() &&  
        TestThird();
 }

これはかさばるように見えますが、何が起こっているかはすぐにわかります。Validate()また、微風の単体テストも行います。

Testxxx()メソッドをコンストラクターのスーパークラスに登録して、自動的に呼び出されるようにすることもできますが、それはより多くの作業であり、おそらく保守性が低くなります。

本当にこれをリフレクションで行いたい場合は、Testxxx()メソッドを属性でマークし、代わりにそれらをリフレクションすることを検討してください。その後、コードは読み取り可能のままです。

于 2009-11-30T11:17:50.363 に答える
0

私が理解している限り、動的ディスパッチは、引数の型に基づいて呼び出すメソッドを決定する必要がある場合に使用されます。あなたの場合、引数なしでメソッドを呼び出すため、動的ディスパッチがこれとどのような関係があるのか​​ わかりません。

手っ取り早いものに対するあなたのアプローチが好きです。製品品質のコードについては、あなたのアプローチには次の潜在的な問題があると思います。

  • 引数の型と戻り値の型をチェックしないため、あなたまたは誰かがメソッドstring CheckWithWrongReturnTypeを追加すると、コードが壊れます。
  • この関数を呼び出すたびに、GetMethods() が呼び出され、リストが処理されます。これはおそらく非効率的です。このリストを配列にキャッシュする方が良いかもしれません。

リフレクションを避けるために、デリゲートを作成し、各クラスがデリゲートのリストを返すようにします。

delegate bool Validator();

bool F1() { return true;  }
bool F2() { return false; }

List<Validator> validators = new List<Validator>(F1, F2);

// 次に、メイン クラスでこれを行うことができます。

foreach(Validator v in validators)
{
   combinedResult &= v();
}
于 2009-11-30T11:30:48.497 に答える