如何为未注册的服务注入null

本文关键字:服务 注入 null 注册 | 更新日期: 2023-09-27 18:04:28

我有一个装饰器和一个相关的服务,看起来像这样:

public interface IAdditionalDataService<TResult, TModel>
{
    TResult PopulateAdditionalData(TResult model, 
        params Expression<Func<TModel, object>>[] properties);
}
public class AdditionalDataDecorator<TQuery, TResult, TModel> 
    : IQueryHandler<TQuery, TResult>
    where TQuery : QueryBase<TResult, TModel>, IQuery<TResult>
    where TModel : ModelBase
{
    private readonly IQueryHandler<TQuery, TResult> _decorated;
    private readonly IAdditionalDataService<TResult, TModel> _additionalDataService;
    public AdditionalDataDecorator(IQueryHandler<TQuery, TResult> decorated,
        IAdditionalDataService<TResult, TModel>  additionalDataService)
    {
        _decorated = decorated;
        _additionalDataService = additionalDataService;
    }
    public TResult Handle(TQuery query)
    {
        var result = _decorated.Handle(query);
        if (query.RelatedDataProperties != null && query.RelatedDataProperties.Any())
            result = _additionalDataService.PopulateAdditionalData(result,
                query.RelatedDataProperties.ToArray());
        return result;
    }
}

装饰器包装了一个查询处理程序,以便AdditionalDataService操作结果然后返回。

问题是不是我所有的查询结果都需要一个AdditionalDataService,所以不是每个可能的结果都有一个相关的AdditionalDataService实现。如果我试图在没有为对应的Type提供有效的AdditionalDataService实现的情况下使用该装饰器,Simple Injector会抛出异常。

我需要简单注入器做什么-仅为AdditionalDataService -是,如果它没有找到一个实现为相应的类型注入"null"。从那里,我可以在调用服务之前测试null。

我的问题是

我如何告诉简单注入器在遇到未注册的服务请求时注入null,而不是抛出异常?

如何为未注册的服务注入null

你应该永远不要null注入到你的应用组件的构造函数中。这是一种不好的做法,因为它会使null检查的代码变得复杂。组件应该总是能够假设它获得了一个值。正因为如此,简单注入器的构建使得它(几乎)不可能注入null值到构造函数中。

相反,您应该使用众所周知的空对象模式,这就是@manji所指的。但是,除了使用ResolveUnregisteredType事件之外,还有一种更简单的方法可以做到这一点。

我假设您使用Register注册IAdditionalDataService<TResult, TModel>实现,就像这样:

// Simple Injector v3.x
container.Register(typeof(IAdditionalDataService<,>),
    new[] { typeof(IAdditionalDataService<,>).Assembly });
// Simple Injector v2.x
container.RegisterManyForOpenGeneric(typeof(IAdditionalDataService<,>),
    typeof(IAdditionalDataService<,>).Assembly);

一个回退注册现在可以注册如下:

// Simple Injector v3.x
container.RegisterConditional(
    typeof(IAdditionalDataService<,>),
    typeof(EmptyAdditionalDataService<,>),
    c => !c.Handled);
// Simple Injector v2.x
container.RegisterOpenGeneric(
    typeof(IAdditionalDataService<,>),
    typeof(EmptyAdditionalDataService<,>));

您可以创建一个 'EmptyAdditionalDataService' (什么都不做),并使用Container将其返回给未注册的服务。ResolveUnregisteredType事件。

你可以在Handled方法中检查它是否是EmptyAdditionalDataService的一个实例