2009-07-07 13 views
1

私は非常に原始的なDIフレームワークを持つことができるようにリゾルバを書いた。フレームワークでは、何も指定されていないか登録されていない場合、依存リゾルバがロードするデフォルトの型を指定することができます。オブジェクトを解決する最善の方法は何ですか?

しかし、デフォルトの読み込み方法は私には不思議に思っています。私はそれができる最善の方法をやっているのか分からない。

例:

T LoadDefaultForType<T>() 
{ 
    T _result = default(T); 

    if (typeof(T) == typeof(ISomeThing) 
    { 
     result = new SomeThing(); 
    } 
    ... more of the same 
    else 
    { 
     throw new NotSupportException("Give me something I can work with!"); 
    } 

    return _result; 
} 

更新

これの使用は、モジュールまたはアセンブリが有するインターフェイスを設定していませんた場合に所定のインターフェイスのためのデフォルトのオブジェクトを取得することであろうコンクリートタイプ。例えばので

:他に何もISomeThingに登録されていない場合

IoC.Resolve<ISomeThing>(); 

は戻って私に何かオブジェクトを返す必要があります。この場合のLoadDefaultForTypeは、デフォルト(この場合は私のドメインモデルが何であれ)を使用するための最後の努力の一種です。

Resolveは、同様にこの上でいくつかの光を当てることがあります

T Resolve<T>() 
{ 
    T _result = default(T); 
    if (ContainedObjects.ContainsKey(typeof(T)) 
     _result = (T)ContainedObjects[typeof(T)]; 
    else 
     _result = LoadDefaultForType<T>(); 
    return _result; 
} 

任意の考えを?コンベンションオーバコンフィグレーションのアプローチを可能にしようとしているので、デフォルトタイプをロードするためのより良い方法がありますか?

答えて

2

提案のいくつか:あなたは、特定のインターフェイスの既定の実装タイプをマークするために使用できる属性を作成することができ

。型を解決しようとすると、Tでこの属性を検索し、リフレクションを使用して型を動的にインスタンス化できます。

また、リフレクションを使用して、使用可能な(ロードされた)アセンブリまたはインターフェイスを実装する具体的なタイプを検索することもできます。これは遅くて高価なプロセスになる可能性があるので、デフォルトのケースがまれである場合にのみ意味をなさないでしょう。

最後に、ネーミング規則に慣れている場合は、インタフェースと同じ名前で、先頭に "I"がないクラスを検索できます。最良のアプローチではありませんが、確かにピンチで働くことができるものです。

+0

私は本当にあなたの属性のアイデアが好きです。私はそれが行く方法かもしれないと思う。 – Joseph

+0

命名規則のアプローチでは、 "convention/configuration"とよく似ています。 – GalacticCowboy

2
public T LoadDefaultForType<T>() 
     where T : new() 
    { 
     T _result = new T(); 

     return _result; 
    } 

は、上記のコードでは、より良い方法でもよいが、それはUに、それはあなたが達成しようとしているであるものは何でもやってのより良い方法を与えるのを助けるだろうyour're TODOをしようと、より多くの情報が何であるかわからないイムでしょう。

動的に読み込むタイプのためにUnityを見てみることをお勧めします。依存性注入

+0

@Neilありがとうございます、私はよく説明するために私の質問を変更します。もし私ができるなら、私は間違いなくDIフレームワークを使用するでしょうが、この場合私は自分自身をロールする以外に選択肢はありません。 – Joseph

+0

@ Neeilまた、Tがインタフェースをサポートしなければならないので、私は新しい制約を使用できません。これは典型的な使用になります。 – Joseph

+0

T:IInterface、new() しかし、これはLoadDefaultTypeがIInterfaceから派生した型しかサポートできないことを意味します。 – Neil

1

ニールのアプローチは、Tを解くことができれば最高です(私も同じアセンブリ内になければならないと思います)。

クラス内では、System.Reflectionで使用できるソートの内部「レジストリ」を作成して、巨大なswitch文を使用せずに項目をインスタンス化することができます。これにより、あなたはDRYを維持しながら、あなたの "コンベンションオーバーコンベンション"を維持します。

編集

いくつかの作業コードを表示するLBushkinの答えの一つの側面と組み合わせます。書かれたとして - - それはアセンブリの境界を越えて動作しないこと

public T LoadDefaultForType<T>() 
{ 
    try 
    { 
    string interfaceName = typeof(T).AssemblyQualifiedName; 

    // Assumes that class has same name as interface, without leading I, and 
    // is in ..."Classes" namespace instead of ..."Interfaces" 
    string className = interfaceName.Replace("Interfaces.I", "Classes."); 

    Type t = Type.GetType(className, true, true); 
    System.Reflection.ConstructorInfo info = t.GetConstructor(Type.EmptyTypes); 

    return (T)(info.Invoke(null)); 
    } 
    catch 
    { 
    throw new NotSupportException("Give me something I can work with!"); 
    } 
} 

注意(少なくとも、それは...私の頭の中でコンパイルし、私は作品を知っている 例から取られています)。ただし、基本的に同じコードを使用して行うことができますが、アセンブリ名をType.GetType()メソッドに指定するだけで済みます。 (固定 - FullNameの代わりにAssemblyQualifiedNameを使用し、インターフェイスと実装クラスが同じアセンブリ内にあることを前提とします。)

+0

正しく理解すれば、デフォルトタイプを上書きすることができないため、Neilのソリューションは法案に適合しません。 –

+0

@ギャラクティック・カウボーイニールのアプローチは私の問題を本当に解決しません。私はもっ​​と説明するために私の質問を更新しました。あなたが記述しようとしていることはまさに私がやろうとしていることですが、それ以外の場合や構造を変更することなく、「レジストリ」を作成するより良い方法はわかりません。私はこの問題を解決するためにどのようにリフレクションを使用するのか分かりませんが、私はアイデアを公開しています。何かの例が本当に役に立つでしょう。 – Joseph

0

1つの方法は、AssemblyQualifiedNameペアのリストを持つことです。最初のペアはベースタイプを含み、2番目のペアは、チャレンジされる子を含みます。それはあなたのApp.configやXMLファイルなど、便利なものであればどこでもかまいません。起動時にこのリストを読んで、ルックアップテーブルとして使用するために辞書を作成するために使用します。キーについては、ベースのAssemblyQualifiedName、またはおそらく対応するTypeインスタンスを使用できます。値としては、おそらく、子タイプのConstructorInfoを取得することを検討する必要があります。

+0

私はあなたと一緒にいますが、コンベンションではなくコンフィグレーションです。私のLoadDefaultForTypeメソッドは、自分のコンベンションの設定についてです。 DIフレームワークには、既にConfigurationを処理するための他のメカニズムがあります。条約部(この部分)は、私が不思議に思っているものです。 – Joseph

+0

TryGetが失敗したため、コンベンションの一部がトリガーされます。その時点で、AQNを受け取り、 "Default"などの標準サフィックスを追加し、Type.GetTypeを使用してそれを調べて、ConstuctorInfoをテーブルに追加することができます。これが失敗した場合は、すべての作業を繰り返さないようにアイデンティティ・エントリを追加してベース・タイプを調べます。これを実行している間、または少なくともアクセスする必要があるときは、テーブルをロックする必要があります。 –

0

デフォルトの型を読み込むより良い方法は、型をハッシュテーブルに格納するaddメソッドを提供することです。これにより、依存関係コンテナが登録ロジックから切り離されます。

登録コードを変更して、ファイルなどの種類を読み取ることができます。

+0

DIフレームワークにもRegisterメソッドがあります。誰でもオブジェクトをインターフェイスに関連付けることで登録することができますが、それは私がフレームワークの構成部分と考えるものです。私が必要とするのは、誰かがインターフェースを設定しないことを選択したときにバックアップ計画を立てることです。 – Joseph

関連する問題