【问题标题】:DryIOC Decorator and InResolutionScopeOfDryIOC 装饰器和 InResolutionScopeOf
【发布时间】:2017-03-07 18:01:56
【问题描述】:

我正在尝试设置一个依赖项,我希望将其注入到(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 的目标,但是在我的 IAsyncRequestHandler 中无法解析 DbContext。

我需要每个 DbContext 实例在源自 IAsyncRequestHandler 解析的任何装饰器或 IActionHandler 中可用,并且该实例也应该注入到 IAsyncRequestHandler 实现中。

关于如何实现这种类型的注入有什么想法吗?

谢谢

【问题讨论】:

  • 我想要实现的基本上是使用 EF DbContexts 的装饰器设置横切关注点,我希望它可以跨 MediatR 请求的任何依赖项使用。执行操作后,我希望能够保存装饰器中的更改。但是,我希望将这种横切逻辑从 MediatR 装饰器中抽象出来,这样它就可以在其他类型的 AOP 中重用,这就是 IActionHandler 介入的地方。也许我对此采取了完全错误的方法,所以我'还将就如何正确建模这一点提出任何建议。
  • 这是先有鸡还是先有蛋的问题。明天我将尝试使用此设置并更新您。
  • 谢谢@dadhi,我知道这有点棘手。

标签: dryioc


【解决方案1】:

更新:

DryIoc 2.8.4 起启用此代码的修复程序可用

旧答案:

DryIoc 从最新版本 2.8.3 开始不支持使用开放泛型类型指定解析范围重用。像这样Reuse.InResolutionScopeOf(typeof(IAsyncRequestHandler&lt;,&gt;)

指定为具体的封闭类型可以正常工作。检查下面的示例 (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

【讨论】:

  • 我已经更新到 2.8.5。并且注入对装饰器正常工作,但它不适用于装饰器的依赖项。在问题的示例中,DbContext 是在 IActionHandler 中注入的,而不是装饰器本身,并且更新后仍然抛出 DryIoc.ContainerException。这是预期的行为吗?
  • 你能用可重现的行为修改我上面的示例并给我一个链接,或者在 bitbucket 中创建一个问题吗?
  • 我已经用依赖检查更新了实时代码并更新到 2.8.5。一切都如我所料。请查收:dotnetfiddle.net/miTXLm
  • 一有机会就去看看,最近比较忙。非常感谢您的帮助
  • 抱歉耽搁了,@dadhi,我认为问题是我覆盖了装饰器的 IActionHandler 参数,设置与你的不太一样。我用我的设置创建了小提琴,你可以看到它抛出了一个异常。 dotnetfiddle.net/HViFi6
猜你喜欢
  • 2017-04-10
  • 1970-01-01
  • 1970-01-01
  • 2013-07-30
  • 2016-11-24
  • 2011-06-06
  • 2015-03-04
  • 2014-03-07
  • 2017-02-14
相关资源
最近更新 更多