我如何将 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
{
}
为 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
{
}