6

私が直面している問題に似た多くの質問と回答を見つけました。しかし、実用的なソリューションをまとめることができませんでした。

私は次のものを持っています:

public interface IProcessing<V,W> where W: TaskResponse where V: TaskRequest
    {
         W process(V req);
    }

TaskRequest&はTaskResponse 抽象基底クラスです

また、この具象クラスが定義されています。

public class MathProcessor : IProcessing<MathRequest, MathResponse>
    {
         public MathResponse process(MathRequest req) {
            // do stuff
            // create a MathResponse instance

            return resp;
        }
    }

ここでMathRequest&MathResponseは派生クラスであり、インターフェイス定義で制約として使用されるそれぞれの抽象クラスです。

インターフェイスに従って具象型を登録し、autofac で解決することは問題ありません。
しかし、実行時に別の型 (この場合は要求オブジェクトなどMathRequest) に基づいて具象型を解決しようとする意図された使用法では、困難が生じます。これは基本的に、メッセージが受信されて適切なハンドラーにディスパッチされる、一般的に見られるメッセージ ハンドラー パターン (疑似コードが続きます) を実現するためのものです。

TaskRequest req = getNextRequest();

var proc = container.Resolve(req.getType().Name)

proc.process(req);

フォーラムの関連トピックに基づいて、基本的な提案は、ファクトリを定義してコンテナに登録し、実行時にファクトリを使用して、指定されたパラメータに基づいて必要なオブジェクトを作成することです。それは正しいようです。

IIndex<K,V>autofacの機能を使用して、適切なタイプ/サービスをキーで検索するという関連する提案も見ています。

MathProcessorキーがタイプであるキーによるタイプの登録と解決に問題があります(この場合はMathRequest)。エラーは、一般的なインターフェイスの定義と許可されているものに関連している可能性があります。

登録:

builder.RegisterType<MathProcessor>().As<IProcessing<MathRequest, MathResponse>>().Keyed<IProcessing<MathRequest, MathResponse>>(strTypeName);

大丈夫ですが、

builder.RegisterType<MathProcessor>().As<IProcessing<TaskRequest, TaskResponse >>().Keyed<IProcessing< TaskRequest, TaskResponse >>(strTypeName);

ではありません。

注:.Netのジェネリック型とco&contravarianceに関するすべての投稿に基づいて、インターフェイスを次のように変更しました:

public interface IProcessing<in V, out W> where W: TaskResponse where V: TaskRequest
    {
         W process(V req);
    }

しかし、それはよく理解していない単なる推測です。私の素朴な見解では、MathProcessor は IProcessing の一種ですが、そうではないようです。

4

1 に答える 1

13

そのタイプの登録は可能ではないと思いますが、一般的な方法で実際の処理を呼び出しているように見えるので、主な目的はリクエストのタイプごとに個別のプロセッサを実装することだと思います。

その場合、BaseProcessing<TV,TW>タイプを作成することで、モデルを少し変更できます。例えば:

public abstract class BaseProcessing<TV, TW> : IProcessing
    where TV : TaskRequest
    where TW : TaskResponse
{
    protected abstract TW DoProcess(TV req);

    public TaskResponse Process(TaskRequest req)
    {
        return DoProcess((TV)req);
    }
}

IProcessingAutoFac に登録する非常に基本的なインターフェイスを実装します。

public interface IProcessing
{
    TaskResponse Process(TaskRequest req);
}

それをベースとして使用して、次のようなプロセッサを作成できます。

public class MathProcessor : BaseProcessing<MathRequest, MathResponse>
{
    protected override MathResponse DoProcess(MathRequest req)
    {
        return new MathResponse();
    }
}

それらを登録する方法の 1 つは、キー付きサービスを使用することです。たとえば、次のようになります。

builder.RegisterType<MathProcessor>().AsImplementedInterfaces().Keyed<IProcessing>(typeof(MathRequest));
builder.RegisterType<OtherProcessor>().AsImplementedInterfaces().Keyed<IProcessing>(typeof(OtherRequest));

この場合、実際には型の名前ではなく、型自体を使用していますが、どちらも機能します。

ここで、キー付きの登録があるということは、別のコンポーネントがそれを依存関係として消費できることを意味します。

public class SomeConsumer : IConsumer
{
    private readonly IIndex<Type, IProcessing> _processors;

    public SomeConsumer(IIndex<Type, IProcessing> processors)
    {
        _processors = processors;
    }

    public void DoStuff()
    {
        var someRequest = new MathRequest();
        var someResponse = _processors[someRequest.GetType()].Process(someRequest);
    }
}
于 2012-12-05T05:34:53.760 に答える