-
-
Notifications
You must be signed in to change notification settings - Fork 4
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
Implemented IServiceProviderIsService #33
Conversation
…r transient services during constructor resolution
nanoFramework.DependencyInjection/DependencyInjection/ServiceProviderEngine.cs
Outdated
Show resolved
Hide resolved
nanoFramework.DependencyInjection/DependencyInjection/ServiceProviderEngine.cs
Outdated
Show resolved
Hide resolved
nanoFramework.DependencyInjection/DependencyInjection/ServiceProviderEngine.cs
Outdated
Show resolved
Hide resolved
The test to see if the service is available from the service provider is something that is wrapped up in the Here is a blog post describing this same issue and how it is resolved in net6 - https://andrewlock.net/exploring-dotnet-6-part-10-new-dependency-injection-features-in-dotnet-6/#detecting-if-a-service-is-registered-in-the-di-container and the original issue in dotnet dotnet/runtime#53919 and the PR that solved that (I totally understand that, aside from the interface, your solution will probably be quite different) - https://github.com/dotnet/runtime/pull/54047/files |
Implemented IServiceProviderIsService
@CZEMacLeod @josesimoes I added and implemented IServiceProviderIsService. This solution ends up being more efficient than the previous I removed my |
nanoFramework.DependencyInjection/System/IServiceProviderIsService.cs
Outdated
Show resolved
Hide resolved
Not directly related to this PR but should |
If we're going to have it, yes. But that one depends heavily on generics which we still don't have. Having said that, let me ask you this: is this for a single specific location in the code? Or do you need this at several methods? |
While looking at the code for this, I think the The current code checks if there are duplicates of the longest constructor length - in the example below there are 3x 2 parameter constructors. using Microsoft.Extensions.DependencyInjection;
internal class Program
{
private static void Main(string[] args)
{
var services = new ServiceCollection();
services.AddSingleton<RegisteredService1>();
services.AddSingleton<RegisteredService2>();
services.AddSingleton<RegisteredService3>();
var serviceProvider = services.BuildServiceProvider();
var test = serviceProvider.GetRequiredService<RegisteredService3>();
Console.WriteLine($"HasService1: {test.HasService1}");
Console.WriteLine($"HasService2: {test.HasService2}");
Console.WriteLine($"HasUnregistered: {test.HasUnregistered}");
}
}
internal class RegisteredService1
{
public RegisteredService1()
{
}
}
internal class RegisteredService2
{
public RegisteredService2()
{
}
}
internal class RegisteredService3
{
private readonly RegisteredService1? service1;
private readonly UnRegisteredService? unRegistered;
private readonly RegisteredService2? service2;
public RegisteredService3(RegisteredService1 service1) => this.service1 = service1;
public RegisteredService3(RegisteredService2 service2) => this.service2 = service2;
public RegisteredService3(RegisteredService1 service1, UnRegisteredService unRegistered) : this(service1) => this.unRegistered = unRegistered;
public RegisteredService3(RegisteredService2 service2, UnRegisteredService unRegistered) : this(service2) => this.unRegistered = unRegistered;
public RegisteredService3(RegisteredService1 service1, RegisteredService2 service2)
{
this.service1 = service1;
this.service2 = service2;
}
public bool HasService1 => service1 != null;
public bool HasService2 => service2 != null;
public bool HasUnregistered => unRegistered != null;
}
internal class UnRegisteredService
{
public UnRegisteredService()
{
}
} |
@CZEMacLeod let's add some unit test to cover this please! 😉 |
Thanks for bringing this up. I saw this and wondered if this was an issue or intentional. My assumption was that something like this should work: public class Service1 : IService1
{
private readonly ILogger _logger;
public Service1(ILoggerFactory loggerFactory): this(loggerFactory.CreateLogger(nameof(Service1)))
{
}
public Service1(ILogger logger = null)
{
_logger = logger;
}
} My expectation was that the first resolvable constructor with the highest number of parameters would be used. It sounds like that expectation isn't the case in MEDI either but should it be? If you open an issue I'll add my two cents there. |
@CoryCharlton In your example MEDI would throw an error if both |
Wow! I'm delighted to see the level of detail and how technical this conversation is! |
Any further developments on this? |
I reviewed the thread and there was lots of discussion but I believe all pending action items for this PR have been resolved. |
@CoryCharlton @josesimoes Yeah - I think the changes/issues I have don't compete with this PR (and I was assuming that any changes would be based off this work). |
Speaking of breaking changes I realized I should probably update the major version with this PR so I just did so. |
Great! Let's have that PR with more fixes/improvements. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK this LGTM!
Thank you again for this nice improvement/fix.
This calls for a bump in version but minor, not major. |
Kudos, SonarCloud Quality Gate passed! 0 Bugs No Coverage information |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks fine to me. Just a reminder we will need to update the samples to support these changes.
I started this work here nanoframework/Samples#332 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm good with it. Sorry wrong account.
Merged. Thank you very much everyone on this so participated PR! 😄 |
Description
GetServiceDescriptors(type)
to retrieve registeredServiceDescriptor
GetService(type)
with call toGetServiceDescriptors(type)
inGetParameters(Type implementationType)
GetParameters(Type implementationType)
as soon as we find out that we cannot support the current constructorMotivation and Context
How Has This Been Tested?
Screenshots
Types of changes
Checklist: