1. ホーム
  2. c#

Reflectionの速度は?

2023-10-12 04:37:22

質問

最近、DataAccessProviderをビジネスロジック層から区別するために、インターフェース層を作成しました。 このアプローチでは、Web/App.Config.の値を変更することによって、いつでも好きなときにDataAccessProviderの選択を変更することができます。 (必要であれば、より詳細な情報を提供することができます)。

とにかく、これを行うために、私たちが作業できるDataProviderクラスを達成するために、リフレクションを使用します。

/// <summary>
/// The constructor will create a new provider with the use of reflection.
/// If the assembly could not be loaded an AssemblyNotFoundException will be thrown.
/// </summary>
public DataAccessProviderFactory()
{
    string providerName = ConfigurationManager.AppSettings["DataProvider"];
    string providerFactoryName = ConfigurationManager.AppSettings["DataProviderFactory"];
    try
    {
        activeProvider = Assembly.Load(providerName);
        activeDataProviderFactory = (IDataProviderFactory)activeProvider.CreateInstance(providerFactoryName);
    }
    catch
    {
        throw new AssemblyNotFoundException();
    }
}

でも今思ったけど、リフレクションってこんなに遅いのか?

どのように解決するのですか?

ほとんどの場合:十分すぎるほど高速です。例えば、DALのラッパーオブジェクトを作成するためにこれを使用する場合、リフレクションによってオブジェクトを作成するのにかかる時間は 極小 ネットワークに接続するのに必要な時間と比較して、です。ですから、これを最適化することは時間の無駄でしょう。

タイトなループでリフレクションを使用している場合、それを改善するためのトリックがあります。

  • ジェネリックス (ラッパー where T : new()MakeGenericType )
  • Delegate.CreateDelegate (型付きデリゲートへ。コンストラクタでは動作しません)
  • Reflection.Emit - ハードコア
  • Expression (例 Delegate.CreateDelegate と似ていますが、より柔軟で、コンストラクタで動作します。)

しかし、あなたの目的のために CreateInstance は全く問題ありません。それにこだわって、物事をシンプルに保ちましょう。


編集:相対的なパフォーマンスについての指摘はそのままで、最も重要なことである「測定する」ことはそのままですが、上記のいくつかを明確にする必要があります。時々...それは はします。 の問題です。まずは測ってみてください。しかし、もしあなたがそれを見つけた場合 が遅すぎると感じたら、次のようなものを見てみるといいかもしれません。 FastMember のような、すべての Reflection.Emit のコードをバックグラウンドで静かに実行し、素晴らしい簡単な API を提供します。

var accessor = TypeAccessor.Create(type);
List<object> results = new List<object>();
foreach(var row in rows) {
    object obj = accessor.CreateNew();
    foreach(var col in cols) {
        accessor[obj, col.Name] = col.Value;
    }
    results.Add(obj);
}

これは単純ですが、非常に高速になります。具体的な例では、DALラッパーについて触れていますが、もしあなたがこれをたくさんやっているのなら、次のようなものを考えてみてください。 ダッパー のようなものを考えてみてください。これはまた、すべての Reflection.Emit のコードをすべてバックグラウンドで行い、可能な限り高速で、かつ使いやすいAPIを提供します。

int id = 12345;
var orders = connection.Query<Order>(
    "select top 10 * from Orders where CustomerId = @id order by Id desc",
    new { id }).ToList();