我如何将 GetAll 与 Ninject 一起使用,以便一次失败不会阻止其他绑定解析?

How do I use GetAll with Ninject so that one failure doesn't stop the other bindings from resolving?

为 mutli 注入提供的某些绑定可能无法解析。

    public List<IMyCommand> GetMyCommands()
    {
        //throws
        return kernel.GetAll<IMyCommand>().ToList();
    }

我仍然希望获得所有成功解析的对象,理想情况下哪些对象失败了。有没有办法用 Ninject 来实现这个?

不是开箱即用的。 但是我们可以创建某种 hack/Workaround。 注意。我宁愿实施一些明确处理我的案件的特定机制,也不愿让 Ninject 参与其中。

但对于那些好奇的人,你可以:

如果你看一下 IResolutionRoot.TryGet 的实现,你会发现它所做的只是捕捉 ActivationException 和 return default(T) 在这种情况下。

我们可以创建自己的 TryGetAll<T> 来做同样的事情,但不是针对整个 IRequest 而是针对每个绑定。所以这是如何做到的:

public static class ResolutionRootExtensions
{
    public static IEnumerable<T> TryGetAll<T>(this IResolutionRoot resolutionRoot)
    {
        var request = resolutionRoot.CreateRequest(
            typeof(IFoo),
            x => true,
            Enumerable.Empty<IParameter>(),
            true,
            false);
        IEnumerable results = resolutionRoot.Resolve(request);
        IEnumerator enumerator = results.GetEnumerator();

        while (MoveNextIgnoringActivationException(enumerator))
        {
            yield return (T)enumerator.Current;
        }
    }

    private static bool MoveNextIgnoringActivationException(
       IEnumerator enumerator)
    {
        while (true)
        {
            try
            {
                return enumerator.MoveNext();
            }
            catch (ActivationException)
            {
            }
        }
    }
}

我已经测试过它并且有效:

public class Test
{
    [Fact]
    public void Foo()
    {
        var kernel = new StandardKernel();

        kernel.Bind<IFoo>().To<FooA>();
        kernel.Bind<IFoo>().To<FooWithDependencyD>();
        kernel.Bind<IFoo>().To<FooB>();
        kernel.Bind<IFoo>().To<FooC>();
        kernel.Bind<IFoo>().To<FooWithDependencyE>();

        kernel.TryGetAll<IFoo>().Should()
            .HaveCount(3)
            .And.Contain(x => x.GetType() == typeof(FooA))
            .And.Contain(x => x.GetType() == typeof(FooB))
            .And.Contain(x => x.GetType() == typeof(FooC));
    }
}

public interface IFoo
{
}

class FooA : IFoo { }

class FooB : IFoo { }

class FooC : IFoo { }

class FooWithDependencyD : IFoo
{
    private readonly IDependency _dependency;

    public FooWithDependencyD(IDependency dependency)
    {
        _dependency = dependency;
    }
}

class FooWithDependencyE : IFoo
{
    private readonly IDependency _dependency;

    public FooWithDependencyE(IDependency dependency)
    {
        _dependency = dependency;
    }
}

internal interface IDependency
{
}