1

最近、いくつかの低レベルのフレームワーク タイプのものでこれを行う必要性に出くわしました。これを達成するためのより良い/よりクリーンな方法があるかどうか、つまり、明らかなまたは巧妙なものが欠けているかどうかを確認したいと思います。 、[ThreadStatic]データをスレッドに関連付けるためにスレッドIDに対する辞書検索を置き換えることを発見したときのように。

私は基本抽象クラスを持っています。それを呼び出しましょうEntityEntityインスタンス化される実際の具象クラスに依存するコンストラクターで、すべての初期化アクションのセットを実行する必要があります。辞書検索と呼び出しを行わずにこれを達成する方法はありthis.GetType()ますか?

ここに私が今持っているものに似たコードがあります:

public abstract class Entity
{
    private static Dictionary<Type, Action<EntityData>> _initActions = new Dictionary<Type, Action<EntityData>>();

    private EntityData _data = new EntityData();

    protected Entity()
    {
        _initActions[this.GetType()].Invoke(_data);
    }
}

public class Employee : Entity
{
    public string Name { get; set; }
}

public class Manager : Employee
{
    public List<Employee> Subordinates { get; set; }
}

Employeeコンストラクターとコンストラクターは、型が異なるためManager、フィールドを異なる方法で初期化する必要があります。_data_initActions コレクションは、インスタンスが新しく作成される前に別のメソッドで初期化されますが、これはこの議論には何の意味もないと思います。

フレームワークのユーザーにとってクラスの使用法をできるだけシンプルに保ちたいので、ユーザーがそれぞれの具象型の Init メソッドを独特または非直感的な方法でオーバーライドするように要求するような奇妙なハックを使用することはできません。

ジェネリックはほとんど機能します。つまりEntity<TEntity>、継承がない場合に TEntity 固有の静的フィールドを取得して init メソッドを格納するようなことができますが、継承をサポートする必要があるため、すべての init メソッドの辞書が必要になります。とにかく、TEntity のサブクラスの場合。

このコードは、かなり低レベルのデータベース エンジン タイプのシナリオで 1m の反復を伴うタイトなループで実行されるため、特定の状況では辞書検索を取り除くことで大幅なスピードアップが得られます (ハッキーな Init オーバーライド実装に置き換えることでテストされています)。

何か案は?

編集:

いくつかのことを明確にしたいと思います。エンティティ エンジンは、その _data コンテナーを初期化するために必要なことを実行するために、_initAction を自動的にセットアップします。ライブラリの「ユーザー」は、このプロセスについて何も知らず、知る必要もありません。私が調べていたのは、基本クラスから型固有の実行時情報を取得するための辞書検索を回避する方法だけですが、それは不可能な場合があります。

はい、これはマイクロ最適化ですが、実際のクエリでこれをテストしたところ、大規模なデータセットをインスタンス化する必要がある一部のクエリでクエリ時間が 15 ~ 20% 短縮されました。

より高速なコードは次のようになります。

public class Employee : Entity
{
    private static EntityInitializer _initMethod = Entity.GetInitMethod(typeof(Employee));

    public string Name { get; set; }

    public Employee()
    {
        _initMethod.Invoke(this);
    }
}

このように、ディクショナリ ルックアップは Employee 型に対して 1 回実行されます。それは恐ろしいことではありませんが、a) すべてのクラスにボイラープレートが必要です。これは私は好きではありません。b) 型パラメーターを現在のクラスと一致させる必要があるため、わずかにエラーが発生しやすくなります。 WPF で依存関係プロパティの間違った所有者クラス名を入力します。ちょっとうまくいくこともありますが、その後、奇妙なバグが発生し、追跡するのが難しくなります。

結局のところ、このデータがアタッチされるこれらすべてのタイプがすべて共通の基本クラスを実装していることを考えると、ディクショナリを使用する以外に、任意のランタイム データをタイプにアタッチするより良い方法はありますか?

4

3 に答える 3

2

タイプを渡す ctor を作成することはできませんか?

    protected Entity(Type type)
    {
        _initActions[type].Invoke(_data);
    }
}

public class Employee : Entity
{
    private static Type mytype = typeof(Employee);
    public string Name { get; set; }
    public Employee(): base(mytype)
    { }
}

ルックアップがパフォーマンスの問題を引き起こしていますか?
辞書検索は 0(1) で、数ミリ秒です。
プログラムは非常に多くのクラスしか持つことができません。
Entity は、オブジェクトを作成し、新しい EntityData を作成し、Invoke を実行する必要があります。
Entity を実装するクラスの初期化に加えて。

于 2013-05-01T16:08:53.750 に答える
0

私はあなたがこれを考えすぎているように本当に感じます. Entityオーバーライドする必要がある抽象的な取得専用プロパティを持たないのはなぜですか?

public abstract class Entity
{
    private static Dictionary<Type, Action<EntityData>> _initActions = 
                new Dictionary<Type, Action<EntityData>>();

    protected abstract EntityData _data { get; }

    protected Entity()
    {
        _initActions[this.GetType()].Invoke(_data);
    }
}

public class Employee : Entity
{
    public string Name { get; set; }
    protected overrides EntityData _data { 
         get { return new EntityData("Employee Stuff"); } 
    }
}

public class Manager : Employee
{
    public List<Employee> Subordinates { get; set; }
    protected overrides EntityData _data { 
         get { return new EntityData("Manager Stuff"); } 
    }
}

または、Init メソッドを 2 つだけ用意します。

public abstract class Entity
{
    private static Dictionary<Type, Action<EntityData>> _initActions = 
                new Dictionary<Type, Action<EntityData>>();

    private void InitalizeBase() { /* do shared construction */ }
    protected abstract void Initalize();

    protected Entity()
    {
        InitalizeBase();
        Initalize();
    }
}

public class Employee : Entity
{
    public string Name { get; set; }
    protected overrides Initalize()
    {
        // Do child stuff
    }
}
于 2013-05-01T16:38:59.533 に答える