c# - 如何为未注册的服务注入(inject) null

标签 c# dependency-injection simple-injector

我有一个装饰器和一个关联的服务,如下所示:

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,因此并非每个可能的 TResult 都有关联的 AdditionalDataService 实现。如果我尝试在没有针对相应类型的有效 AdditionalDataService 实现的情况下使用装饰器,则简单注入(inject)器会抛出异常。

我需要 Simple Injector 做的 - 仅适用于 AdditionalDataService - 如果它没有找到相应类型的实现,则注入(inject)“null”。从那里我可以在调用服务之前测试 null。

所以我的问题是

如何告诉 Simple Injector 在遇到对尚未注册的服务的请求时注入(inject) null,而不是抛出异常?

最佳答案

你不应该永远注入(inject)null进入应用程序组件的构造函数。这是一种不好的做法,因为它会使带有空值检查的代码变得复杂。一个组件应该总是能够假定它获得了一个值。正因为如此,Simple Injector 的构建使其(几乎)无法注入(inject) null值到构造函数中。

相反,您应该使用众所周知的 Null Object pattern ,这就是@manji 所指的。但不是使用 ResolveUnregisteredType事件,有一种更简单的方法可以做到这一点。

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

// 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<,>));

就是这样。

关于c# - 如何为未注册的服务注入(inject) null,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31600492/

相关文章:

asp.net-mvc - 每个 Web 请求的 EF DbContext + Custom RoleProvider = 每个 Web 请求或单例的 RoleProvider?

dependency-injection - guice注入(inject)器在哪里存放?

Scala 蛋糕模式鼓励硬编码依赖关系?

c# - 如何在不知道类型的情况下转换泛型类型

c# - 如果变量为空,则不要在 SQL WHERE 子句中包含变量

python - 为什么 python 没有 Spring DI(组件生命周期)框架?

c# - Hangfire RecurringJob + 简单注入(inject)器 + MVC

multithreading - Simpleinjector : Is this the right way to RegisterManyForOpenGeneric when I have 2 implementations and want to pick one?

c# - 在 C# 中,什么是 "is"关键字的等价物,但使用 Type 对象

c# - 动态 HTML 内容 - "A potentially dangerous Request.Form value was detected from the client"