Skip to content
This repository was 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

@pakrym pakrym force-pushed the pakrym/validator branch from 0b98f06 to 04d3a02 Compare July 14, 2016 15:42
@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

@pakrym pakrym force-pushed the pakrym/validator branch from 04d3a02 to 5e290f4 Compare July 14, 2016 15:48

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.

@pakrym pakrym force-pushed the pakrym/validator branch from 5fbb2cd to 89f641f Compare July 14, 2016 17:46
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 pakrym force-pushed the pakrym/validator branch from 0711554 to 0773feb Compare July 14, 2016 21:13
@pakrym pakrym force-pushed the pakrym/validator branch from 0773feb to 9d352ad Compare July 14, 2016 21:20
@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 pakrym force-pushed the pakrym/validator branch from 1d2d7e1 to 3e3724c Compare July 15, 2016 15:40
@pakrym
Copy link
Contributor Author

pakrym commented Jul 15, 2016

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

@pakrym pakrym force-pushed the pakrym/validator branch from 3e3724c to 462ff92 Compare July 15, 2016 15:46
@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.

7 participants