3

私の質問を単純化してみましょう:

管理者、ユーザー、プレイヤー、ロールの 4 つのクラスがあります。

データベースは、実行する必要があるメソッドの名前を返します。たとえば、Admins_GetNameが返された場合、クラスGetName()でメソッドを実行する必要があります。が返されたAdmins場合、クラスでメソッドを呼び出す必要があります。Players_GetRankGetRank()Players

すべてのビジネス ロジックを含む巨大な IF または SWITCH ステートメントを記述したくありません。リフレクションを使用しない最も効率的なソリューションは何でしょうか? 可能であれば、リフレクションがもたらすパフォーマンスへの影響を避けたいと思います。

すべてのメソッドは異なるパラメーターを持つ場合がありますが、文字列を返すことに注意してください。

これが私が今やろうと考えていることです: 1) データベースの値を分解し、実行する必要があるクラスとメソッドを見つける switch ステートメントを含むメソッドを用意します。何かのようなもの:

switch(DbValue)
{
 case DbValue == "Admins_GetName":
  Declare a delegate to Admins.GetName();
  return;
 case: DbValue = "Players_GetRank"
  Declare a delegate to Players.GetRank();
  return;
  . 
  .
  .
  etc
}

クラス/メソッド参照を返します。

2) 上記の宣言を次の場所に渡します。

var myValue = Retrieved method.invoke()

これを達成するための最良の方法を提案してもらえますか、それを実装する方法についての私のアイデアの正しい構文を教えてください。

ありがとうございました。

4

1 に答える 1

5

もう少しコンテキストが必要です。たとえば、問題のすべてのメソッドが同じ署名を持っているか? 一般的に、リフレクションはこれに最も適したツールであり、タイトなループで呼び出していない限り問題ありません。

それ以外の場合、switchステートメント アプローチは合理的ですが、メンテナンス オーバーヘッドがあります。それが問題になる場合は、実行時にデリゲート キャッシュを作成したくなるでしょう。次に例を示します。

using System;
using System.Collections.Generic;
public class Program
{
    public string Bar { get; set; }

    static void Main()
    {
        var foo = new Foo();
        FooUtils.Execute(foo, "B");
        FooUtils.Execute(foo, "D");
    }
}
static class FooUtils
{
    public static void Execute(Foo foo, string methodName)
    {
        methodCache[methodName](foo);
    }
    static readonly Dictionary<string, Action<Foo>> methodCache;
    static FooUtils()
    {
        methodCache = new Dictionary<string, Action<Foo>>();
        foreach (var method in typeof(Foo).GetMethods())
        {
            if (!method.IsStatic && method.ReturnType == typeof(void)
                && method.GetParameters().Length == 0)
            {
                methodCache.Add(method.Name, (Action<Foo>)
                    Delegate.CreateDelegate(typeof(Action<Foo>), method));
            }
        }
    }
}

public class Foo
{
    public void A() { Console.WriteLine("A"); }
    public void B() { Console.WriteLine("B"); }
    public void C() { Console.WriteLine("C"); }
    public void D() { Console.WriteLine("D"); }
    public string Ignored(int a) { return ""; }
}

このアプローチは、ジェネリックを使用して複数のターゲット タイプに拡張できます。

static class FooUtils
{
    public static void Execute<T>(T target, string methodName)
    {
        MethodCache<T>.Execute(target, methodName);
    }
    static class MethodCache<T>
    {
        public static void Execute(T target, string methodName)
        {
            methodCache[methodName](target);
        }
        static readonly Dictionary<string, Action<T>> methodCache;
        static MethodCache()
        {
            methodCache = new Dictionary<string, Action<T>>();
            foreach (var method in typeof(T).GetMethods())
            {
                if (!method.IsStatic && method.ReturnType == typeof(void)
                    && method.GetParameters().Length == 0)
                {
                    methodCache.Add(method.Name, (Action<T>)
                        Delegate.CreateDelegate(typeof(Action<T>), method));
                }
            }
        }
    }
}
于 2012-12-19T06:38:39.360 に答える