2

アプリケーション用に一種の拡張可能なデータ レイヤーを作成しようとしています。「リポジトリ」の 1 つは、抽象ストア クラスのインメモリ実装です。

public abstract class Store<TEntity, TIdentifier> : IStore<TEntity, TIdentifier>
        where TEntity : StorableEntity<TIdentifier>        
{
  //abstract methods here

  public abstract TIdentifier GetUniqueIdentifier();
}

「StorableEntity」抽象クラスは次のとおりです。

public abstract class StorableEntity<TIdentifier>
{
    public TIdentifier ID { get; set; }
}

次のような「InMemoryStore」と呼ばれる Store の具体的なクラスがあります。

public class InMemoryStore<T, U> : Store<T, U>
    where T : StorableEntity<U>
{
    protected static Dictionary<U, T> store = new Dictionary<U, T>();

    public override U GetUniqueIdentifier()
    {
    // call relevant "generator" here - SOMETHING LIKE THIS??
    // var generator = GetGeneratorSomehow(U);
    // return generator.Create();
    }
}

さて、ここでの「U」の型は、string、int、Guid などの可能性があります... (ほとんどの場合、int である可能性があります)

ここでの私の考えは、次のような IUIDGenerator のようなものを作成することです:

public interface IUIDGenerator<T>
{
    T Create(ICollection<T> collection);
}

上記の「InMemoryStore」では、IUIDGenerator のインスタンスを作成し、ストア ディクショナリのキー コレクションを渡し、「Create」メソッドを呼び出して、必要な型の一意の識別子を返します。

たとえば、このような IntUIDGenerator クラスを持つことができます (これは、辞書キーに既に含まれている数値に基づいて、一種の増分数値ジェネレーターとして機能します)

public class IntUIDGenerator : IUIDGenerator<int>
{
    public int Create(ICollection<int> collection)
    {
        var result = collection.Max() + 1;
        if (collection.Contains(result))
            return result;

        throw new NotUniqueException();
    }
}

実際の質問: 私がしなければならないことは、InMemoryStore 内で、U の型 (識別子の型) を識別し、必要な IUIDGenerator の具体的な実装を動的に選択できるようにすることです - どうすればこれを行うことができますか?

クラス ファクトリ パターンのタイプを持つことを考えました - 利用可能なすべての UIDGenerators を辞書にロードします...しかし、それらはすべて異なるタイプを持つことができますか?

これを回避するより良い方法はありますか?

また、質問のタイトルが少しずれている可能性があることも認識しています。より良い提案があれば、お気軽にコメントしてください。変更します。

4

4 に答える 4

2

Unity、 Castle 、Ninjectなどの IoC フレームワークを使用できます。次に、次のようにコンテナーを構成します。

_container = new UnityContainer();
_container.RegisterType<IUIDGenerator<int>, IntUIDGenerator);
_container.RegisterType<IUIDGenerator<Guid>, GuidUIDGenerator);

次に、クラスには次のようなものがあります。

public override U GetUniqueIdentifier()
{
    var generator = _container.Resolve<IUIDGenerator<U>>();
    return generator.Create();
}
于 2010-07-15T22:23:51.300 に答える
0

少なくとも 1 つのキャストを使用する必要があると思います。すべてのジェネレーターを次のようなマップに保存する場合

Map<Type, object> generators;

あなたが使用することができます

class InMemoryStore<T,U> {
  public override U GetUniqueIdentifier() {
    var generator = generators[typeof(U)] as IUIDGenerator<U>;
    return generator.Create(collection);
  }
}

もちろん、私はすべての種類の検証コードを省略しました:)(タイプのジェネレーターUがマップにあるかどうかのチェックなど...)

于 2010-07-15T22:22:00.183 に答える
0

簡単な答え:依存性注入を使用し、DI コンテナーに処理させます。

于 2010-07-15T22:22:29.337 に答える
0

ジェネレーターに追加のジェネリック型引数を追加できます。

public class InMemoryStore<T, U, V> : Store<T, U>
    where T : StorableEntity<U>
    where V : IUIDGenerator<U>, new() {

    public override U GetUniqueIdentifier()
    {
        return (V)(Activator.CreateInstance<V>()).Create();
    }
}
于 2010-07-15T22:43:45.153 に答える