4

アプリケーションでさまざまな種類のドキュメントを同じ方法で処理したい したがって、次のような汎用インターフェイスがあります。

public interface IDocHandler<T>where T: class
{

T Document { get;set;}

void Load(T doc);

void Load(string PathToDoc);

void Execute();

void Execute(T doc);

}

そして、さまざまな種類のドキュメントに対して、このインターフェイスを実装します。

例えば:

public class FinanceDocumentProcessor:IDocumentHandler<ReportDocument>
{} 


public class MarketingDocumentProcessor:IDocumentHandler<MediaDocument>
{} 

次に、もちろん次のようなことができます。

IDocumentHandler<ReportDocument> docProc= new FinanceDocumentProcessor();

上記の行を疎結合にするために、実行時に T を注入する方法を知ることは興味深いでしょう...

IDocumentHandler<ReportDocument> docProc = container.resolve("FinanceDocumentProcessor());

しかし、構成ごとに、FinanceDomcumentProcessor または MarketingDocumentProcessor を使用するかどうかを決定したい...したがって、左側のサイトにも T を注入する必要があります... c# 2.0 を使用する必要があるため、魔法の言葉は使用できませんこの場合、「var」は非常に役立ちます...しかし、これをオープンで柔軟に設計するにはどうすればよいですか...


誤解して申し訳ありませんが、すべてのコメントに感謝しますが、私の課題には別の例があります (おそらく、間違った設計を使用している可能性があります) ...しかし、試してみます: 同じ状況ですが、異なる説明

私が持っている画像の例:

ReportingService、Crystal、ListAndLabel 3 つの異なるレポート ドキュメント タイプ。私は一般的なハンドラーIReportHandler<T>(上記と同じ) を持っています。このハンドラーは、レポート ドキュメントを処理するためのすべての機能を提供します。例えば

ChrystalReportHandler:IReportHandler<CrystalReportDocument>

Reportingservicesここで、Unity のようなフレームワーク (または他のフレームワーク) を依存性注入に使用して、Crystal を使用するか、リストとラベルを使用するかを構成によって決定したいと考えています。

マッピングを指定すると、 my を注入できますChrystalReportHandlerが、どのように T を左側に注入できますか、より良い言葉で言えば のタイプReportDocument.

IReportHandler<T (this needs also to be injected)> = IOContainer.Resolve(MyMappedType here) 

私の問題はもちろん左側のサイトですが、それはタイプに結合されていますが、マッピングがあります...マッピングに基づいてオブジェクトを生成し、マッピングされたタイプを割り当てることは可能でしょうか? または基本的に左側にもTを注入しますか?または、このアプローチはこの状況には適していません。

4

3 に答える 3

2

IDocumentHandler現在の設計では、 と特定の Document (ReportDocumentまたはMediaDocument)の間に「依存関係」を作成していると思います。そのためIDocumentHandler<ReportDocument or MediaDocument>、コードで直接使用する場合は、コンテナーがそれを提供すると想定する必要があります。この場合、コンテナーはドキュメント タイプの解決を担当するべきではありません。

このようにデザインを変更することを検討してみませんか?

public interface IDocumentHandler
{
    IDocument Document { get; set; }

    void Load(IDocument doc);

    void Load(string PathToDoc);

    void Execute();

    void Execute(IDocument doc);

}

public class IDocument { }
public class ReportDocument : IDocument { }
public class MediaDocument : IDocument { }
public class FinanceDocumentProcessor : IDocumentHandler { }
public class MarketingDocumentProcessor : IDocumentHandler { }
于 2008-12-10T10:20:02.277 に答える
1

左側で非ジェネリックインターフェイスを使用する必要があります。

試す:

public interface IDocumentHandler { }
public interface IDocumentHandler<T> : IDocumentHandler { }

これにより、2つのインターフェイスが作成されます。T固有ではない一般的なものはすべてベースインターフェイスに配置し、その他はすべて汎用インターフェイスに配置します。

オブジェクトを解決したいコードで、プロセッサのタイプがわからないため、とにかくT固有のコードを呼び出すことができなかったため、 -汎用インターフェース。


編集:私の答えが反対票を投じられていることに気づきました。物事に反対票を投じる人々がなぜそうしたのかコメントを残してくれるといいのですが。レピュテーションポイントは気にしません。現時点ではマイナーなノイズですが、回答に重大な問題がある場合は、回答を削除できるようにしたいと思います(ターゲットから外れている場合)。 )または修正します。

この場合、元の質問者が反対票を投じたために十分な情報を投稿していないため、実際に質問以外のことを質問しているか、私の回答を完全に理解していなかったのではないかと思います。それは少し短かったので理解できます、またはそれを理解していなかった誰かが同じ理由でそれを反対票を投じました。

さて、詳しく説明します。

「左側」には何も注入できません。それは可能ではありません。そのコードはコンパイルされ、正しく、コンパイル時に100%「そこに」存在する必要があります。その部分については、「実行時にTが何であるかを教えてあげる」とは言えません。それは不可能です。

したがって、残っているのはTを完全に削除することだけです。依存関係を使用するコードをTにまったく依存しないようにします。または、少なくとも、リフレクションを使用してTが何であるかを発見し、その知識に基づいて物事を実行します。

それがあなたにできることのすべてです。右側のメソッドから何を返すかによって、左側のコード自体を変更することはできません。

それは不可能です。

したがって、私の答え。

于 2008-12-10T09:39:10.847 に答える
1

私の理解が正しければ、選択肢は 2 つあります。

  1. インターフェイス IDocHandler とそれを実装する複数のクラスがある場合は、次のようにタイプを明示的に登録する必要があります。

    container.AddComponent>(typeof(FooHandler));

  2. クラスDocHandlerが1つある場合は、オープンジェネリック型を使用してコンポーネントに登録できます

    container.AddComponent(typeof(IDocHandler<>), typeof(DocHandler<>));

IDocHandler を解決するたびに DocHandler のインスタンスを取得し、 IDocHandler を解決すると DocHandler を取得します

それが役立つことを願っています

于 2008-12-22T22:27:02.440 に答える