Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WithConcreteTypeDynamicRegistrations hides failed dependency resolution #506

Closed
Haukinger opened this issue Jul 27, 2022 · 5 comments
Closed
Assignees
Labels
enhancement New feature or request
Milestone

Comments

@Haukinger
Copy link

Normally, one gets an explicit message when a dependency fails to resolve (e.g. no concrete type registered for a given interface), like

 Unable to resolve IDependency as parameter "dependency"

When I use WithConcreteTypeDynamicRegistrations, though, this info disappears from the exception message and I just get

Unable to resolve resolution root Service

Reproduction steps:

internal class Program
{
    private static void Main(string[] args)
    {
        var containerWithNiceException = new Container();
        containerWithNiceException.Register<Service>();
        try
        {
            containerWithNiceException.Resolve<Service>();
        }
        catch (ContainerException)
        {
            //code: Error.UnableToResolveUnknownService;
            //message: Unable to resolve IDependency as parameter "dependency"
            //    in resolution root Service FactoryId = 30
            //from container without scope
            //Where no service registrations found
            //    and no dynamic registrations found in 0 of Rules.DynamicServiceProviders
            //    and nothing found in 0 of Rules.UnknownServiceResolvers}
        }

        var containerWithNondescriptException = new Container(rules => rules.WithConcreteTypeDynamicRegistrations(reuse: Reuse.Transient));
        try
        {
            containerWithNondescriptException.Resolve<Service>();
        }
        catch (ContainerException)
        {
            //code: Error.UnableToResolveFromRegisteredServices;
            //message: Unable to resolve resolution root Service
            //from container without scope
            //with Rules with { UseDynamicRegistrationsAsFallbackOnly}
            //with normal and dynamic registrations:
            //(DefaultDynamicKey(0), { FactoryID = 31, ImplType = Service, Reuse = TransientReuse, HasCondition})
        }

    }
}

internal class Service
{
    public Service( IDependency dependency )
    {
    }
}

internal interface IDependency
{
}
@dadhi
Copy link
Owner

dadhi commented Jul 27, 2022

Thanks. I will look.

@dadhi
Copy link
Owner

dadhi commented Jul 27, 2022

@Haukinger From your second example, you did not register Service,
so that's why the exception says that the resolution root Service is unresolved.

If you register the root Service,

containerWithNondescriptException.Register<Service>();

then the exception will be very similar to the first example: Unable to resolve IDependency as parameter "dependency"

@Haukinger
Copy link
Author

It was my expectation that WithConcreteTypeDynamicRegistrations is there to be able to resolve concrete types (like Service in the example) without prior registration like Unity does, for example. This works fine and without exception if either Service has no dependency or the dependency is registered.

That's the problem I have with the exception in the second example - it looks like there's a problem with Service while the problem's the missing registration of IDependency.

@dadhi
Copy link
Owner

dadhi commented Jul 28, 2022

@Haukinger Huh you are right.

Ok, The problem is more subtle.
When DI tries to create the not registered service it probes all available candidates.. and it looks at service dependencies as well. If not satisfied it moves to the next cadidate loosing the details of the problem with the previous one.

I definitely can make it better.
Will look further. Cheers.

@dadhi dadhi self-assigned this Jul 31, 2022
@dadhi dadhi added the enhancement New feature or request label Jul 31, 2022
@dadhi dadhi added this to the v5.2.0 milestone Jul 31, 2022
@dadhi dadhi closed this as completed in 065e319 Jul 31, 2022
@dadhi
Copy link
Owner

dadhi commented Jul 31, 2022

I have added the overload WithConcreteTypeDynamicRegistrations(IfUnresolved ifConcreteTypeIsUnresolved, Func<Type, object, bool> condition = null, IReuse reuse = null) (will be out with v5.2.0).

If you specify WithConcreteTypeDynamicRegistrations(IfUnresolved.Throw) then you will get the desired behavior.

I did not change the original behavior because there are cases when you have multiple dynamic rules in place, and there is a rule after the WithConcreteTypeDynamicRegistrations which suppose to fallback for unresolved concrete type.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants