DryIOC 装饰器和 InResolutionScopeOf
DryIOC Decorator and InResolutionScopeOf
我正在尝试设置一个依赖项,我想将其注入到(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<,> 中解析。
我需要每个 DbContext 实例在源自 IAsyncRequestHandler<,> 的解析的任何装饰器或 IActionHandler 中可用,并且该实例也应该注入到 IAsyncRequestHandler<,> 实现中。
关于如何实现这种类型的注入有什么想法吗?
谢谢
更新:
启用此代码的修复自 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;
}
}
}
我创建了一个 issue 以将支持添加到下一个版本中。
作为替代方案,您可以使用不带类型的密钥,如下所示:
container.Register<DbContext, Model1>(reuse: Reuse.InResolutionScopeOf(serviceKey: blah));
但是你还需要用密钥注册你 IAsyncRequestHandler
。
我正在尝试设置一个依赖项,我想将其注入到(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<,> 中解析。
我需要每个 DbContext 实例在源自 IAsyncRequestHandler<,> 的解析的任何装饰器或 IActionHandler 中可用,并且该实例也应该注入到 IAsyncRequestHandler<,> 实现中。
关于如何实现这种类型的注入有什么想法吗?
谢谢
更新:
启用此代码的修复自 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;
}
}
}
我创建了一个 issue 以将支持添加到下一个版本中。
作为替代方案,您可以使用不带类型的密钥,如下所示:
container.Register<DbContext, Model1>(reuse: Reuse.InResolutionScopeOf(serviceKey: blah));
但是你还需要用密钥注册你 IAsyncRequestHandler
。