Skip to content
This repository has been archived by the owner on Nov 2, 2018. It is now read-only.

Validate scope into singleton sevice injection #430

Merged
merged 4 commits into from
Jul 15, 2016
Merged

Conversation

pakrym
Copy link
Contributor

@pakrym pakrym commented Jul 14, 2016

@@ -9,7 +9,12 @@ public static class ServiceCollectionContainerBuilderExtensions
{
public static IServiceProvider BuildServiceProvider(this IServiceCollection services)
{
return new ServiceProvider(services);
return BuildServiceProvider(services, false);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: style validateScopes: false

@davidfowl
Copy link
Member

Make that style change where the optional parameter syntax is used everywhere

@davidfowl
Copy link
Member

I think there's value in being able to catch this at startup time before the first resolve.

@pakrym
Copy link
Contributor Author

pakrym commented Jul 14, 2016

Indeed there is but service provider is lazy for a reason and some of them could not be caught, like open generics use cases ISingleton<T> where T is IHaveScopedService


namespace Microsoft.Extensions.DependencyInjection.ServiceLookup
{
internal struct CallSiteValidatorState
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make this nested inside CallSiteValidator? It's not used outside of it.

@pranavkm
Copy link
Contributor

⌚ for the few questions.

return BuildServiceProvider(services, validateScopes: false);
}

public static IServiceProvider BuildServiceProvider(this IServiceCollection services, bool validateScopes)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Time for doc comments? On one hand, I kind of hope no one ever uses this (except for may us). On the other hand, without context, I would have no idea what validateScopes is even about.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the other method + type too since they're all public.

@halter73
Copy link
Member

halter73 commented Jul 14, 2016

Is the issue we want to identify really a scoped service being injected into a singleton (perhaps transitively). Or is the issue even more fundamental, should we vialidate that a scoped service is never resolved from the root? We might have to validate on every call to GetService for that (since a CallSite could be built for a scoped resolution, but then used later from the root container), but it should be simple.

@pakrym
Copy link
Contributor Author

pakrym commented Jul 14, 2016

🆙📅

{
internal class CallSiteValidator: CallSiteVisitor<CallSiteValidator.CallSiteValidatorState, Type>
{
private readonly Dictionary<Type, Type> _scopedServices = new Dictionary<Type, Type>();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment to indicate the key is the service being resolved via GetService and the value is a single scoped service that it depends on (but there may be more.

@halter73
Copy link
Member

:shipit:

/// </summary>
/// <param name="services">The <see cref="IServiceCollection"/> containing service descriptors.</param>
/// <param name="validateScopes">
/// <c>true</c> to perform check verifying that scoped services never gets resolved from root provider; otherwise <c>false</c>.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might as well point out false is the default behavior.

@pranavkm
Copy link
Contributor

:shipit:

@khellang
Copy link
Contributor

In relation to @halter73's comment; I've always wondered what happens if/when you resolve a scoped service from the top-level container... Does it effectively become a singleton?

@khellang
Copy link
Contributor

If that's the case, you have (at least) two ways a scoped/transient service can be held captive; either as a dependency of a singleton/scoped service or in the top-level provider.

@pakrym
Copy link
Contributor Author

pakrym commented Jul 15, 2016

@khellang yes, this PR is targeting these two scenarios.

@halter73
Copy link
Member

🚢

@cwe1ss
Copy link

cwe1ss commented Aug 19, 2016

This is a great addition! Since it is now defined that resolving scoped services from a non-scoped provider should not be possible, shouldn't this also be covered in the Specification.Tests library to make sure other containers don't allow this either?

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

Successfully merging this pull request may close these issues.

None yet

7 participants