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

Question: How to work with dependency overrides from factory method? #105

Closed
schuettecarsten opened this issue Aug 22, 2021 · 14 comments
Closed

Comments

@schuettecarsten
Copy link
Contributor

I can use RegistrationConfigurator.WithFactory to register a factory method. That's fine. But now I need to check for specific dependency overrides in that factory method. If a class is not available in the dependency overrides, I want to handle this myself in the factory (by calculating a specific default value that might change from time to time).

Is that possible?

@schuettecarsten schuettecarsten changed the title Get dependency overrides from factory method Question: How to access dependency overrides from factory method? Aug 22, 2021
@schuettecarsten schuettecarsten changed the title Question: How to access dependency overrides from factory method? Question: How to work with dependency overrides from factory method? Aug 22, 2021
@z4kn4fein
Copy link
Owner

Hi there, unfortunately, there is no way to access the resolution request's ResolutionContext from a factory. I'll investigate how much effort would it take to make the current context publicly available for the resolution tree.

In the meantime, could you explain your case a bit more? Is it a must to access the overrides?

@schuettecarsten
Copy link
Contributor Author

I plan to use dependency overrides to pass parameters into the constructor and need to make sure that the parameters instance(s) is/are passed as dependency override and are not created as transient dependency by Stashbox itself.

z4kn4fein added a commit that referenced this issue Aug 23, 2021
@z4kn4fein
Copy link
Owner

I came up with an idea and pushed it into the pre-release channel, here you can check the test for the usage.

What do you think?

z4kn4fein added a commit that referenced this issue Aug 23, 2021
@schuettecarsten
Copy link
Contributor Author

schuettecarsten commented Aug 23, 2021

Thank you for the very good solution. During my tests, I ran info a new issue: It is not possible to tell the UnknownRegistrationConfigurator to not resolve an unknown type if the service type is a class type. In that case, the UnknownRegistrationConfigurator is already initialized correctly, so that if (!registrationConfigurator.TypeMapIsValid(out _)) in line 42 in UnknownTypeResolver is always false.

I did not find a working solution with the current implementation, as context.SetImplementationType(typeof(void)); and context.SetImplementationType(null); both fail.

I have added a method to UnknownRegistrationConfigurator:

         /// <summary>
        /// Resets the current registration's implementation type and factory settings.
        /// </summary>
        /// <returns>The configurator itself.</returns>
        public UnknownRegistrationConfigurator Reset()
        {
            base.ImplementationType = null;
            this.Context.Factory = null;
            this.Context.FactoryParameters = null;
            this.Context.IsFactoryDelegateACompiledLambda = false;

            return this;
        }

To make this work, a null check must be added to RegistrationConfiguration.TypeMapIsValid in line 39:

        internal bool TypeMapIsValid(out string error)
        {
            error = null;
            if (this.ImplementationType == null)
            {
                error = $"Implementation type not set.";
                return false;
            }

            if (this.Context.Factory != null)
                return true;

Unfortunately, this also breaks dependency overrides as Stashbox does the dependency override check after it checks for registration validity. So, dependency overrides currently cannot be used to pass values into types that are not yet registered.

@z4kn4fein
Copy link
Owner

z4kn4fein commented Aug 23, 2021

So, you want to tell in the unknown type configurator to DO NOT resolve some types, right?

Then, I would approach this in a different way. What do you think about this syntax: Skip<TypeToSkip1>().Skip<TypeToSkip2>() and Skip(IEnumerable<Type> typesToSkip)?

This list would be checked in the resolver to skip the containing types from resolution.

Or just a general Skip() method that could be used in a conditional statement like:

if (ctx.ServiceType == typeof(TypeToSkip) || ...) 
{
    ctx.Skip();
}

@schuettecarsten
Copy link
Contributor Author

schuettecarsten commented Aug 23, 2021

Yes, but this makes it neccessary for me to process all types that I do not want to register, which might be thousands. At the moment, I do this check when StashBox tries to resolve an unknown type. I did not recognize yet that it will always resolve class types.

I have updated the pull request #106 - renamed the Reset() method to Skip(), which simply resets the factory and implementation type of the context, and added a check for dependency overrides.

@z4kn4fein
Copy link
Owner

Alright, after a second thought I also ended up with the second solution, it feels more granular for the context. I checked your PR and I rather introduce a new bool property where we store the info about skipping. Also, the dependency override check is not relevant at that point because the unknown type resolution is executed far after the override search.
Or is there another case you wanted to cover with that?

@schuettecarsten
Copy link
Contributor Author

I added the dependency override check there because I ran into an ResolutionFailedException when I tried to pass an instance as depencency override and Skip the unknown type resolution. So yes, the override search runs before, but resolution still fails.

That's why I am unhappy with my solution, as the whole resolving stuff is not neccessary for types that are already available as dependency override.

@z4kn4fein
Copy link
Owner

That sounds weird, it shouldn't be picked by the unknown resolution when it's available as override. Let me check this out. Do you have a quick failing example? Thanks!

@schuettecarsten
Copy link
Contributor Author

schuettecarsten commented Aug 24, 2021

Your solution with Skip works like a charm and has no errors with dependency overrides. My exception was caused by my implementation. Thank you!

@schuettecarsten
Copy link
Contributor Author

schuettecarsten commented Aug 24, 2021

Coming back to the original question, also your test code works fine. But unfortunately, there is no WithFactory method that accepts a generic parameter on RegistrationConfigurator.

Update - I have added the following methods to src/Registration/Fluent/RegistrationConfigurator.cs, see my pull request.

@z4kn4fein
Copy link
Owner

I merged your PR and made those methods available for decorators, also, gave them some tests. Could you please try the latest version? Thanks!

@schuettecarsten
Copy link
Contributor Author

Thank you, now everything works as expected.

@z4kn4fein
Copy link
Owner

Changes are released in v3.6.4

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

No branches or pull requests

2 participants