Ninject 多个绑定取决于 ctor 参数名称

Ninject multiple bindings depending on ctor parameter name

假设我有如下界面:

public interface ISomething { };

public interface IResolver
{
    string ResolveBy(ISomething something);
}

现在我有两种解析器类型;一个提供最佳解决方案,但有可能失败的解决方案和一个解析器,它总是 return 一个解决方案,应该作为后备策略:

public class UnsafeResolver : IResolver
{
    Random random = new Random();

    public string ResolveBy(ISomething something)
    {
        if (random.NextDouble() > 0.5)
        {
            return "best solution ever!";
        }
        else
        {
            throw new InvalidOperationException("something went wrong...");
        }
    }
}

public class SafeResolver : IResolver
{
    public string ResolveBy(ISomething something)
    {
        return "fallback solution";
    }
}

现在我想在 safeguarded 组合装饰器中组合两个解析器:

public class SafeguardedResolver : IResolver
{
    private readonly IResolver unsafeResolver;
    private readonly IResolver safeResolver;

    // This is the problem with Ninject: Two parameters with same interface...
    public SafeguardedResolver(IResolver unsafeResolver, IResolver safeResolver)
    {
        // guards omitted!
        this.unsafeResolver = unsafeResolver;
        this.safeResolver = safeResolver;
    }

    public string ResolveBy(ISomething something)
    {
        try
        {
            return unsafeResolver.ResolveBy(something);
        }
        catch (InvalidOperationException)
        {
            return safeResolver.ResolveBy(something);
        }
    }
}

所以我的问题是:如何在不使用的情况下使用Named Binding策略实现与Ninject的绑定?我不希望对我域中的容器有任何依赖性 类,因此建议的解决方案对我不起作用

当然不用将 ctor 更改为 IEnumerable<IResolver> - 我想要两个单独的 明确命名的 参数!

为什么不能通过参数名称定义绑定?例如这样的事情:

Bind<IResolver>().To<SafeguardedResolver>();
Bind<IResolver>().To<UnsafeResolver>()
    .WhenInjectedInto<SafeguardedResolver>()
    .AsParameter("unsafeResolver");
Bind<IResolver>().To<SafeResolver>()
    .WhenInjectedInto<SafeguardedResolver>()
    .AsParameter("safeResolver");

不是可以通过反射获取参数名称吗?

我希望有人能给我一个答案,如何解决这个问题(也许通过使用另一个 DI 框架?)或者为什么这是不可能的。

I do not want any dependencies to the container in my domain classes

您可以在不从 class 库引用容器的情况下使用命名绑定,方法如下:

StandardKernel kernel = new StandardKernel();

kernel
    .Bind<IResolver>()
    .To<SafeguardedResolver>()
    .WithConstructorArgument("unsafeResolver", c => c.Kernel.Get<IResolver>("unsafe"))
    .WithConstructorArgument("safeResolver", c => c.Kernel.Get<IResolver>("safe"));

kernel
    .Bind<IResolver>()
    .To<UnsafeResolver>()
    .Named("unsafe")
    .BindingConfiguration.IsImplicit = true;

kernel
    .Bind<IResolver>()
    .To<SafeResolver>()
    .Named("safe")
    .BindingConfiguration.IsImplicit = true;

这里是你如何用 Pure DI 做同样的事情:

var result = new SafeguardedResolver(new UnsafeResolver(), new SafeResolver());

Pure DI 在此类情况下的简单性是 IMO it is better than using a container 的原因之一。