DryIOC装饰器和InResolutionScopeOf

时间:2016-10-25 15:39:06

标签: dryioc

我试图设置一个依赖项,我希望将其注入基础接口(MediatR处理程序)的解析范围:

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

但是,这个接口正在设置一些装饰器,这些装饰器依赖于IActionHandler,而IActionHandler依赖于DbContext:

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

我试图解决IActionHandler的实现时遇到异常,因为它无法注入DbContext,因为它似乎在范围内不可用。

我已尝试将IActionHandler设置为InResolutionScopeOf的目标,但DbContext无法在我的IAsyncRequestHandler&lt;,&gt;中解析。

我需要每个DbContext实例可以在任何装饰器或IActionHandler中使用,这些装饰器或IActionHandler来自IAsyncRequestHandler&lt;,&gt;的解析,并且该实例也应该注入IAsyncRequestHandler&lt;,&gt;实施

关于如何实现这种注射的任何想法?

由于

1 个答案:

答案 0 :(得分:1)

更新

DryIoc 2.8.4

以来,可以使用启用此代码的修复程序

旧答案:

最新版本2.8.3的DryIoc不支持使用open-generic类型指定解析范围重用。像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;
        }
    }
}

我创建了issue以将支持添加到下一个版本中。

另外,您可以使用不带类型的密钥,如下所示:

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

但是你需要用密钥注册IAsyncRequestHandler