当Autofac尝试通过依赖项解析器解析构造函数参数时,有没有办法一次列出所有缺失的注册?或者是一次通过一个的唯一方法..
以此为例:
public MyWebApiController(IMyInterface myInterface)
我知道实现IMyInterface的类MyInterfaceImpl必须使用Autofacs ContainerBuilder这样注册:
builder.RegisterType<MyInterfaceImpl>().As<IMyInterface>()
但是,如果MyInterfaceImpl依赖于其他10个构造函数,并且每个构造函数依赖于一个handfull,那该怎么办呢?有没有办法让Autofac遍历所有尚未在ContainerBuilder中注册的依赖项,而不是在它上面抛出DependencyResolutionException。第一次出现?
采取:
public MyInterfaceImpl(IMyInterface2 myInterface2, IMyInterface3 myInterface3, ... etc ...)
每个都有自己的构造函数需要注册..
public MyInterface2Impl(IMyInterfaceB myInterfaceB)
等
因为我缺少Autofac注册,所以显示以下异常消息,告诉我必须使用接口注册即MyInterface2Impl。
没有找到的构造函数 &#39; Autofac.Core.Activators.Reflection.DefaultConstructorFinder&#39;在类型上 &#39; MyWebApiController&#39;可以使用可用的服务调用 参数
详细显示了拒绝的参数:
无法解析参数&#39; IMyInterface2 myInterface2&#39;构造函数 &#39; Void .ctor(IMyInterface2 myInterface2,IMyInterface3 myInterface3, ......等等......)
但是我可能拥有的下5次失踪注册都没有。这是一个烦恼,因为我必须启动网站/服务并在我修复的每次丢失注册后调用api控制器,并且在设置coctail时有时可能会有很多丢失的注册。
那么,Autofac可以立即向我显示所有缺失的注册吗?
答案 0 :(得分:2)
没有简单的方法可以做你想做的事。我检查代码,只显示第一个参数,请参阅ConstructorParameterBinding.cs in github repository
for (int i = 0; i < parameters.Length; ++i)
{
var pi = parameters[i];
bool foundValue = false;
foreach (var param in availableParameters)
{
Func<object> valueRetriever;
if (param.CanSupplyValue(pi, context, out valueRetriever))
{
_valueRetrievers[i] = valueRetriever;
foundValue = true;
break;
}
}
if (!foundValue)
{
CanInstantiate = false;
_firstNonBindableParameter = pi;
break;
}
我认为这是出于性能原因。
顺便说一下,你可以使用ResolveOperationBeginning
事件来获得你想要的特定情况。
#if DEBUG
container.ResolveOperationBeginning += (sender, e) =>
{
IComponentRegistration registration = null;
e.ResolveOperation.InstanceLookupBeginning += (sender2, e2) =>
{
registration = e2.InstanceLookup.ComponentRegistration;
};
e.ResolveOperation.CurrentOperationEnding += (sender2, e2) =>
{
if (e2.Exception != null)
{
ConstructorInfo ci = registration.Activator.LimitType
.GetConstructors()
.First();
StringBuilder sb = new StringBuilder();
sb.AppendLine($"Can't instanciate {registration.Activator.LimitType}");
foreach (ParameterInfo pi in ci.GetParameters())
{
if (!((ILifetimeScope)sender).IsRegistered(pi.ParameterType))
{
sb.AppendLine($"\t{pi.ParameterType} {pi.Name} is not registered");
}
}
throw new DependencyResolutionException(sb.ToString(), e2.Exception);
}
};
};
#endif
它在所有情况下都不会起作用,但如果你只使用没有复杂绑定的构造函数注入,那就足够了。