1

Is there a way to list all missing registrations at once, when Autofac tries to resolve constructor parameters through dependency resolver? Or is the only way to go through one at a time..

Take this as an example:

public MyWebApiController(IMyInterface myInterface)

I know that the class MyInterfaceImpl that implements IMyInterface has to be registered like this with Autofacs ContainerBuilder:

builder.RegisterType<MyInterfaceImpl>().As<IMyInterface>()

But what if MyInterfaceImpl depends on 10 other constructors, and each of them depends on a handfull.. Is there a way to let Autofac go through all dependencies that have not been registered with the ContainerBuilder, instead of throwing a DependencyResolutionException on the first occurence?

Take:

public MyInterfaceImpl(IMyInterface2 myInterface2, IMyInterface3 myInterface3, ... etc ...)

And each of these have their own constructors that need to be registered..

public MyInterface2Impl(IMyInterfaceB myInterfaceB)

etc.

Because I have missing Autofac registrations, the following exception message shows, telling me I have to register i.e. MyInterface2Impl with the interface.

None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'MyWebApiController' can be invoked with the available services and parameters

And details showing which parameter it rejects:

Cannot resolve parameter 'IMyInterface2 myInterface2' of constructor 'Void .ctor(IMyInterface2 myInterface2, IMyInterface3 myInterface3, ... etc ...)

But nothing about the next 5 missing registrations I possibly have. This is an annoyance, because I have to start up the site/service and call the api controller, after every missing registration I fix, and sometimes there can be a lot of missing registrations, when setting up the coctail.

So, can Autofac show me ALL the missing registrations at once?

Cyril Durand
  • 15,834
  • 5
  • 54
  • 62
Bogmag
  • 49
  • 7

1 Answers1

4

There is no easy way to do what you want. I check the code and only the first parameter is displayed, see 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;
    }

I think this is for performance reason.

By the way, you can use the ResolveOperationBeginning event to get what you want for your specific case.

#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

It won't work in all case but if you only use constructor injection without complex binding it should be enough.

Complete sample here : https://dotnetfiddle.net/om16sI

Cyril Durand
  • 15,834
  • 5
  • 54
  • 62