c# - 使用 Simple Injector 将开放通用类型注册为回退

标签 c# .net dependency-injection simple-injector

设置

我正在使用 the almighty SimpleInjector3 连接的 .NET4.0 上运行 Web 应用程序.我正在使用 Command-/QueryHandler architecture described here我在为命令处理程序配置依赖项时遇到问题。

示例代码

这是类结构的分解:

interface ICommandHandler<T> 
{
    void Handle(T command);
}

enum LoggingState { Success, Failed }

interface ICommandLogger<T>
{
    void Log(LoggingState state, T command);
}

class NullCommandLogger<T> : ICommandLogger<T>
{
    void Log(LoggingState state, T command)
    {
        // Intentionally left blank
    }
}

装饰器:

/// <summary>
/// The logging command handler that gets wrapped around every
/// command handlers.
/// </summary>
class LoggingCommandHandlerDecorator<TCommand> : ICommandHandler<TCommand>
{
    private readonly ICommandHandler<TCommand> decorated;
    private readonly ICommandLogger<TCommand> logger;

    public LoggingCommandHandlerDecorator(
        ICommandHandler<TCommand> decorated,
        ICommandLogger<TCommand> logger)
    {
        this.decorated = decorated;
        this.logger = logger;
    }

    public void Handle(TCommand command)
    {
        try
        {
            this.decorated.Handle(command);
        }
        catch (Exception)
        {
            this.logger.Log(LoggingState.Failed, command);
            throw;
        }

        this.logger.Log(LoggingState.Success, command);
    }
}

在我的 CompositionRoot 中,我这样配置它:

var assembly = /* Get the assembly where the handlers are located */

// Register all explicitly defined loggers
container.Register(typeof(ICommandLogger<>), assembly);

// Register null objects for everything else
container.RegisterConditional(
    typeof(ICommandLogger<>),
    typeof(NullCommandLogger<>),
    ctx => !ctx.Handled);

// Wrap all command handlers with the logging
container.RegisterDecorator(
    typeof(ICommandHandler<>),
    typeof(LoggingCommandHandlerDecorator<>));

这对于像这样的非通用记录器非常有效:

class WorkingLogger : ICommandLogger<SomeCommand> { /* ... */ }

问题

现在我有一组实现标记接口(interface)的命令,这样我就可以为所有这些使用一个记录器——但这不会被 SimpleInjector 拾取:

class NotWorkingLogger<T> : ICommandLogger<T>
    where T : IMarkerInterface { /* ... */ }

我知道这不应该是差异问题,但我已经尝试使用 variance extensions只是为了确定但无济于事。

有没有办法配置这个场景?

最佳答案

您只需添加 NotWorkingLogger<T> 的注册即可明确如下:

container.Register(typeof(ICommandLogger<>), assembly);

// It's added between the two other registrations
container.RegisterConditional(
    typeof(ICommandLogger<>),
    typeof(NotWorkingLogger<>),
    ctx => !ctx.Handled);

container.RegisterConditional(
    typeof(ICommandLogger<>),
    typeof(NullCommandLogger<>),
    ctx => !ctx.Handled);

关于c# - 使用 Simple Injector 将开放通用类型注册为回退,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32143320/

相关文章:

c# - 使用接口(interface)松耦合 NoSQL 提供程序

c# - WPF工具包 : Type reference cannot find a public type

c# - 使用 Linq 遍历 ConfigurationManager.ConnectionStrings?

c# - 如何获得*互联网* IP?

.net - 你如何获得正则表达式的组名?

java - @Inject 和 @Autowired 不起作用,而使用 setter 注入(inject)则有效

c# - 代码组织 : How to best group functions, 类等

c# - 两个 docker 容器之间的 Dotnet SSL 错误

c# - 超高性能套接字服务器 - 实现细节

grails - 如何将springSecurityService注入(inject)自定义监听器