1

基本インターフェース (MediatR ハンドラー) の解決スコープに注入したい依存関係をセットアップしようとしています:

container.Register<DbContext, Model1>(reuse: Reuse.InResolutionScopeOf(typeof(IAsyncRequestHandler<,>)));

ただし、このインターフェイスは、DbContext に依存する IActionHandler に依存するいくつかのデコレータでセットアップされています。

public class Decorator<TRequest, TResponse> : IAsyncRequestHandler<TRequest, TResponse>
{
    public Decorator(IActionHandler handler, IAsyncRequestHandler<TRequest, TResponse> inner);
}

その IActionHandler の実装を解決しようとして例外が発生しました。これは、スコープ内で使用できないように見えるため、DbContext を挿入できないためです。

IActionHandler を InResolutionScopeOf のターゲットに設定しようとしましたが、IAsyncRequestHandler<,> で DbContext を解決できません。

各 DbContext インスタンスが、IAsyncRequestHandler<,> の解決に由来するすべてのデコレーターまたは IActionHandler で使用できるようにする必要があり、そのインスタンスは IAsyncRequestHandler<,> 実装にも挿入する必要があります。

このタイプの注射をどのように達成できるかについてのアイデアはありますか?

ありがとう

4

1 に答える 1

1

アップデート:

このコードを有効にするための修正は、DryIoc 2.8.4以降で利用できます。

古い答え:

最新バージョン 2.8.3 の DryIoc は、オープン ジェネリック タイプでの解決スコープの再利用の指定をサポートしていません。そのようにReuse.InResolutionScopeOf(typeof(IAsyncRequestHandler<,>)

具体的な閉じた型として指定するとうまくいきます。以下のサンプルを確認してください ( live ):

using System;
using DryIoc;

public class Program
{
    public static void Main()
    {
        var c = new Container();


        c.Register<IActionHandler, SomeActionHandler>();

        c.Register<IAsyncRequestHandler<string, string>, SomeRequestHandler>();

        // works with closed-generic spec.
        c.Register<DbContext, Model1>(reuse: Reuse.InResolutionScopeOf(typeof(IAsyncRequestHandler<string, string>)));

        // Error: not working with open-generic type in reuse spec
        // c.Register<DbContext, Model1>(reuse: Reuse.InResolutionScopeOf(typeof(IAsyncRequestHandler<,>)));

        c.Register(typeof(IAsyncRequestHandler<,>), typeof(Decorator<,>), setup: Setup.Decorator);

        var result = c.Resolve<IAsyncRequestHandler<string, string>>();

        Console.WriteLine("decorator: " + result);
        Console.WriteLine("decorator.DbContext is the same as action handler's: " + 
                          (result.DbContext == ((Decorator<string, string>)result).ActionHandler.DbContext));
    }

    public interface IAsyncRequestHandler<TRequest, TResponse> 
    {
        DbContext DbContext { get; }
    }

    public interface IActionHandler 
    {
        DbContext DbContext { get; }
    }

    public class DbContext {}

    public class Model1 : DbContext {}

    public class Decorator<TRequest, TResponse> : IAsyncRequestHandler<TRequest, TResponse>
    {
        public DbContext DbContext { get { return _decorated.DbContext; } }

        IAsyncRequestHandler<TRequest, TResponse> _decorated;

        public readonly IActionHandler ActionHandler;

        public Decorator(IActionHandler handler, IAsyncRequestHandler<TRequest, TResponse> inner) 
        {
            ActionHandler = handler;
            _decorated = inner;
        }
    }

    public class SomeRequestHandler : IAsyncRequestHandler<string, string> 
    {
        public DbContext DbContext { get; private set; }

        public SomeRequestHandler(DbContext dbContext) 
        {
            DbContext = dbContext;
        }
    }

    public class SomeActionHandler : IActionHandler 
    {
        public DbContext DbContext { get; private set; }

        public SomeActionHandler(DbContext context) 
        {
            DbContext = context;
        }
    }
}

次のバージョンにサポートを追加するイシューを作成しました。

別の方法として、次のようにタイプのないキーを使用することもできます。

container.Register<DbContext, Model1>(reuse: Reuse.InResolutionScopeOf(serviceKey: blah));

IAsyncRequestHandlerただし、キーも登録する必要があります。

于 2016-10-28T08:02:51.327 に答える