【问题标题】:Resolve as null instead of an exception解析为 null 而不是异常
【发布时间】: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&lt;T&gt;。但是,底层包提供了一个默认实现(它是内部的,所以我们不能一般地注册它),以防我们没有该T 的实现。在这种情况下,我们根本不应该调用.WithBarService 方法。

但是,如果我们不注册IBarService&lt;T&gt;,我们会从容器中得到一个异常,因为它无法解决它。

那么问题来了:当它无法为某些T 解析IBarService&lt;T&gt; 时,是否可以将容器配置为返回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&lt;T&gt; 实现,并使用该“空实现”作为备用注册,以防给定T 不存在显式实现。大多数 DI 容器允许您注册这种回退行为。
  • @Steven,谢谢。这实际上已经到位。这就是我所说的基本包已经提供的默认行为的意思。我明确不想在这个包中重复它,默认的是包内部的。

标签: c# dependency-injection dryioc


【解决方案1】:

当它无法为某些 T 解析 IBarService 时,是否可以将容器配置为返回 null 而不是抛出?或者有没有其他方法可以解决这个问题?

您可以将IBarService&lt;T&gt;参数设为可选,如果服务未注册,容器不会抛出:

public SomeFactory( IFooService fooService, IUnderlyingFactory factory,
IBarService<T> barService = null) { _fooService = fooService, _barService = barService, _factory = factory }

或者你可以配置服务注入IfUnresolved.ReturnDefault选项。

container.Register(typeof(SomeFactory<>), 
  made: Parameters.Of.Type(typeof(IBarService<>), ifUnresolved: IfUnresolved.ReturnDefault))

注意:我可能会弄错最后一个的语法,但应该是这样的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-13
    • 2020-08-31
    相关资源
    最近更新 更多