【发布时间】:2019-12-06 12:35:34
【问题描述】:
在我们的一个项目中,我们有以下场景:我们有一个工厂,它使用它的工厂创建另一个包的服务(我们的工厂基本上配置了底层工厂)。底层工厂使用流畅的语法,一个最小的示例如下所示:
public class SomeFactory<T> where T: class
{
private readonly IFooService _fooService;
private readonly IBarService<T> _barService;
private readonly IUnderlyingFactory _factory;
public SomeFactory(
IFooService fooService, IBarService<T> barService, IUnderlyingFactory factory)
{
_fooService = fooService,
_barService = barService,
_factory = factory
}
public SomeService<T> Create()
{
return _factory
.WithFooService(_fooService)
.WithBarService(_barService)
.Create();
}
}
现在手头的问题:对于一些T,我们已经实现了IBarService<T>。但是,底层包提供了一个默认实现(它是内部的,所以我们不能一般地注册它),以防我们没有该T 的实现。在这种情况下,我们根本不应该调用.WithBarService 方法。
但是,如果我们不注册IBarService<T>,我们会从容器中得到一个异常,因为它无法解决它。
那么问题来了:当它无法为某些T 解析IBarService<T> 时,是否可以将容器配置为返回null 而不是抛出?或者有没有其他方法可以解决这个问题?
如果我们收到null,我们可以将 Create 方法更改为:
public SomeService<T> Create()
{
var service = _factory.WithFooService(_fooService);
if (_barService != null){
_factory.WithBarService(_barService);
}
return _factory.Create();
}
为了完整起见,这就是我们为某些T 注册BarService 的方式,即通过对实现类型的反射:
container.RegisterMany(
ourAssembly.GetTypes()
.Where(type => type.GetInterfaces().Any(i => i.IsGenericType
&& !type.IsAbstract)));
【问题讨论】:
-
我对 DryIoc 不太熟悉,但总的来说,此类问题最好使用 Null Object 设计模式来解决。这意味着您应该创建一个不包含任何行为的空的通用
IBarService<T>实现,并使用该“空实现”作为备用注册,以防给定T不存在显式实现。大多数 DI 容器允许您注册这种回退行为。 -
@Steven,谢谢。这实际上已经到位。这就是我所说的基本包已经提供的默认行为的意思。我明确不想在这个包中重复它,默认的是包内部的。
标签: c# dependency-injection dryioc