-
Notifications
You must be signed in to change notification settings - Fork 33
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
.NET8 GetServices issue orleans8 #315
Comments
The problem is described here: Because I've done a quick search to check in Orleans code how Your issue would happen when no such service is registered and Grace attempts to locate these on its own anyway, and fails because it doesn't know how to locate It really reminds me of #309, even though you said Keep in mind I haven't had time to debug, this is just intuition and maybe not everything above is correct. Just to be sure: you've combined the .net 8 Grace branch with the latest |
Yes, i pulled your branches and built local nugets with those (key services works now). Now added a sample of keyed service + included grace projs in the sample
No, not that part, I already posted how they are doing it above, which is this one just in case you missed it: Registration in Microsoft Orleans (not our source)UPDATE NOTE: this doesn't get invoked when debugging public static IServiceCollection AddGrainDirectory<T>(this IServiceCollection collection, string name, Func<IServiceProvider, string, T> implementationFactory)
where T : IGrainDirectory
{
collection.AddSingleton(sp => new NamedService<IGrainDirectory>(name, implementationFactory(sp, name)));
// Check if the grain directory implements ILifecycleParticipant<ISiloLifecycle>
if (typeof(ILifecycleParticipant<ISiloLifecycle>).IsAssignableFrom(typeof(T)))
{
collection.AddSingleton(s => (ILifecycleParticipant<ISiloLifecycle>)s.GetGrainDirectory(name));
}
return collection;
}
Thanks!! i was missing the ctor to replicate it, now i managed to isolate it in the unit test 🥳 using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Specification;
using System;
using Xunit;
namespace Grace.DependencyInjection.Extensions.Tests
{
public class GraceContainerTests : DependencyInjectionSpecificationTests
{
protected override IServiceProvider CreateServiceProvider(IServiceCollection serviceCollection)
{
void Configuration(InjectionScopeConfiguration x) => x.Behaviors.AllowInstanceAndFactoryToReturnNull = true;
//return new DependencyInjectionContainer(Configuration)
return new DependencyInjectionContainer()
.Populate(serviceCollection);
}
[Fact]
public void GetServices()
{
var services = new ServiceCollection()
//.AddSingleton(sp => new NamedService<StrategyIndex> { Name = "strat1", Value = new StrategyIndex() })
//.AddSingleton(sp => new NamedService<StrategyIndex> { Name = "strat2", Value = new StrategyIndex() })
.AddSingleton(sp => new NamedService<IHeroesIndex>("wow", new HeroesIndex()))
//.AddKeyedSingleton("strat", (sp, k) => new NamedService<StrategyIndex> { Name = "statA", Value = new StrategyIndex() })
//.AddKeyedSingleton("strat", (sp, k) => new NamedService<StrategyIndex> { Name = "statB", Value = new StrategyIndex() })
//.AddSingleton(sp => new NamedService<IHeroesIndex> { Name = "name", Value = new HeroesIndex() })
;
var providers = CreateServiceProvider(services);
var q = providers.GetServices<NamedService<IHeroesIndex>>();// ?? Enumerable.Empty<NamedService<IHeroesIndex>>();
Assert.NotEmpty(q);
// returns 1 single entry when no services are registered with null data (not expected)
var strats = providers.GetServices<NamedService<StrategyIndex>>();// ?? Enumerable.Empty<NamedService<IHeroesIndex>>();
// returns empty when no services are registered (expected)
var stratsKeyed = providers.GetKeyedServices<NamedService<StrategyIndex>>("strat");
}
}
}
public class NamedService<TService>
{
public NamedService(string name, TService service)
{
Name = name;
Service = service;
}
public string Name { get; }
public TService Service { get; }
}
public interface IHeroesIndex
{
}
public class HeroesIndex : IHeroesIndex
{
}
public class StrategyIndex
{
} |
collection.AddSingleton(sp => new NamedService<IGrainDirectory>(name, implementationFactory(sp, name))); Ok thanks for finding that code for me! You mention that it doesn't get called, so we're back at Grace trying to fulfill unregistered exports. Without debugging, the behavior I would expect is:
I will debug the simple repro when I have time to and let you know if I find something. |
UPDATE: @jods4 tested the same unit test with the current master and it works, alto with this unexpected behavior (at least to me) which i posted above #315 (comment) |
Well, it looks exactly like #309. I have created this small test case, without MS DI: With With This is a can of worms, so I'm hesitant to fix it myself -- and #309 was already failing for similar cases in 7.0. The fact you use If you can I would suggest staying away from both |
@stephenlautier In case you'd want to keep Just to ensure there is no unintended regression here I ran the same test on Grace 7.2 and got the same result (Could not locate type String). @ipjohnson It is unfortunate that out of the box, Grace fails with obscure errors when using some important libraries, such as MassTransit or Orleans. I can think of three possible ways to improve the situation, all of which would be breaking changes: 1. Be more specific in ShouldCreateConcreteStrategyThis was my first idea but I don't quite like it. Firstly, it's practically impossible to account for all the ways a ctor parameter can be injected. Adding conditions is going to be a trade-off between false positive (creating a registration that's impossible to fulfill) and false negative (not auto-registering something that could be). Even if the change was narrow and targeted at this issue, say: don't use ctor with primitive or Second, from a DX perspective I like the current flow better. If you perform 2. Don't auto-register collectionsIn the same spirit that It's a weird use-case because auto-registration only works with concrete types, and locating an auto-registered The drawback of this is that if anyone depends on this, there's no workaround to the breaking change, beside explicit registration. 3. AutoGenerateUnknowns = false by defaultThis is my favorite. The migration from Grace 7 for users that depend on For new users, I think it's a better default. I think people expect a DI framework (in general) to require registration before usage. I would bet most users are unaware that they have auto-registration potentially going on behind the scenes. And the problem with auto-registration is that it's wonky and unpredictable. It's easy to register things you don't want (and maybe don't notice: internal options from libraries for example), with inappropriate lifetimes. What do you think? |
@jods4 Thanks for you suggestions RE: Our code makes use of the |
@stephenlautier did you see my last comment above? If you depend on auto-registration you can also just exclude |
Yes, thank you i've seen it. That would make it easier to switch; but I agree with your statements above so changing from our end its also good thing. Now im looking into another issue, not sure if its a Grace issue or not so far as im trying to narrow it down, but it is possible though. |
Let me know if you find a regression. |
@jods just in case i created another issue which is #316 (comment) related to the issue i described above |
As per the discussion in this thread and specifically using jods4:net8 PR branch
Will open an new issue so not to clutter the other thread
During startup Im having the following exception (which is not from our code but from Orleans)
Full stacktrace
Alto seeing the code its seems "intended" as its marked as required and no default
Usage in Microsoft Orleans (not our source)
https://github.com/dotnet/orleans/blob/main/src/Orleans.Runtime/Hosting/DirectorySiloBuilderExtensions.cs#L71
Registration in Microsoft Orleans (not our source)
UPDATE NOTE: this doesn't get invoked when debugging
https://github.com/dotnet/orleans/blob/main/src/Orleans.Runtime/Hosting/DirectorySiloBuilderExtensions.cs#L42
This is our config for grace (though tried to comment the Behaviors but still the same)
Not sure if we need to configure something specifically, or its a bug
To isolate the issue, I added a very basic test to test similar what they are doing however that succeeds
test source
Also replicated the issue with a basic Orleans sample (and also isolate it from our stuff)
AdventureServer
You should get the above exception on launch
The text was updated successfully, but these errors were encountered: