-
Notifications
You must be signed in to change notification settings - Fork 47
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
Keyed Services Support in dotnet 8 #112
Comments
I've been following the development of that since the initial proposal and have a branch started to work on it. I'm currently blocked by a runtime issue in unit testing multiple frameworks that I think will be fixed in preview 7, but that's stopping the build from targeting net8 right now. I'm not sure what work will be involved to support the new feature. I know there's an attribute based injection for constructor filtering by key so there may need to be a core Autofac change to accommodate that. But... stuck on runtime at the moment. |
Finally got to a computer where I could install preview 7 and, sure enough, it does fix the unit test problems I was seeing so I can actually get back to this now. |
I'm continuing to work on this in my branch, but there are some interesting concepts that got added to the Microsoft registrations that I'm not 100% sure how to bridge for Autofac. Null keys: Microsoft added a thing where you can do Any keys: There's a placeholder/wildcard concept Keyed service factories: If you register a factory delegate, it takes in the key as a parameter and it generates keyed services. I'm not totally clear on whether that means it's a factory that generates keyed things or whether it's a keyed factory, or maybe both. I gather you could combine this with the I'm discovering this stuff through the spec tests and I'm working on trying to figure out how these concepts adapt to Autofac. I'm not totally sure they all do, at least, not easily. |
Progress has been made, but not much. The There's a notion where the keyed service registration is passed, as a parameter, the key used to resolve the thing, which, also, is not a construct Autofac natively supports. I have this sort of figured out for reflection registrations, I still have no real good idea of what to do for delegates. It does not help that my day job continues to eat more of my time and mental capacity, so working long hours and then switching from staring at a screen to staring at a different screen is not really something I'm motivated to do. |
The
All of this adds up to not really being able to patch this onto our adapter using only existing Autofac extension points. It means we actually need to support this I'm unclear where this leaves things. I can't finish it in this repo alone, but I also currently have neither the time nor motivation to work on the core Autofac changes. I can't help but feel a bit of tail-wagging-the-dog on the Microsoft side of things, with their conforming container now adding features we already mentioned were going to be non-trivial to bridge and implement. Yet here we are. I don't have an answer. Don't bother pinging for status, if I get to it, you'll see it show up; if I don't, you won't. And that's pretty much it. If you want to do the work and submit the PR for it, awesome. We'd love to see it. |
Hello, do you have any updates on this issue? How can we help to push this problem? We used Autofac provider for all our services, and moving to .net 8 causes error: "This service descriptor is keyed. Your service provider may not support keyed services" |
Generally if the are updates to issues you'll see them in the issue or as a release. Since there are neither, you can assume no update. We determined that something needs to change in core Autofac to support this new construct. Keyed services in MEDI are quite different than keyed services in Autofac. While we have the I wish I could offer more, but, as mentioned, the features Microsoft added to the conforming container are, in some cases, very different than the features in Autofac to support keyed services. It means a lot of work to change how Autofac does things and it'll likely result in since breaking changes in core Autofac to make this happen. For future commenters: updates here will be provided if there are updates. If you don't see any, it's because there's nothing to add. The work will not be fast, and I can't lie, between unpaid maintainer burnout and my paid day job ramping up hard to eat my free time and motivation, I'm not personally actively cranking hard to solve this. |
@tillig, I'm thinking of maybe picking this up for my vacation pet-project (don't want to give you any false hopes though), and have a couple of questions:
|
@srogovtsev We'd absolutely welcome the help. Let me see if I can lay out where things are and the issues I've run into that pushed me toward modifying core Autofac. The There is a set of specification tests in the The primary set of features, high level, are:
Handling standard keyed service registrations is fairly trivial. It's a basic conversion from their registration syntax to Autofac. Injection of the key as a parameter gets a little more tricky, but it's not that bad, at least for reflection-based components. I already have some middleware that handles it. However, I didn't get to a point where I got the delegate registrations to inject the parameter as an input to the delegate. About this time is when I started running into trouble, and the first issue I hit was what sort of type casting they allow for the key being injected. Maybe an example to help explain. Let's say you have a class like this: public class MyKeyedComponent
{
public MyKeyedComponent([FromKey]string key)
{
}
} In this case, when you register the thing... builder.RegisterType<MyKeyedComponent>().Keyed<MyKeyedComponent>("the-key"); and then resolve it... container.ResolveKeyed<MyKeyedComponent>("the-key"); ...the parameter passed into the constructor will be However, it seems like you should be able to do this: public class MyKeyedComponent
{
public MyKeyedComponent([FromKey]object key)
{
}
}
// ALL of these should work.
container.ResolveKeyed<MyKeyedComponent>("the-key");
container.ResolveKeyed<MyKeyedComponent>(17);
container.ResolveKeyed<MyKeyedComponent>(new DivideByZeroException()); So if the key gets injected into the constructor as a parameter, what are the legal conversions that can happen? I started out trying to do my best to convert it to be compatible but it turns out there are tests that have some conversions being not allowed and providing I haven't yet really figured out which conversions are allowed and which aren't. Does it have to be exact match? Does it allow casting down from something to object? If the constructor parameter takes an integer and someone resolves with an This is where I started getting wrapped around the axle a little with What's the lifetime scope handling on In Autofac, this is easy to figure out: builder.RegisterType<SomeType>().Keyed<SomeType>("key").Keyed<SomeType>("otherkey").SingleInstance(); If you resolve with But let's look at
So now we have a situation where the lifetime scope on a single service that got registered - a service registered with I didn't even get to the point of figuring out open generic registrations (but I think it was generally working), delegate registrations, or And that's where it sits. As mentioned, we'd love the help if you have the time. And if any of the stuff I mentioned needs clarification or you're curious about other aspects of what's in the branch, definitely let me know. |
Thinking out loud: From a core Autofac perspective, it's like the concept of a keyed component, at least one registered with I say it's between there because:
Maybe that means changing the order in which registration sources are evaluated - evaluate them in the same order as components instead of a separate evaluation order. Again, just thinking out loud/taking notes. Not recommending anything. |
The idea on top of my head is based on the question whether we even want to support the M.E.DI behavior in Autofac; I mean, how much of a cognitive problem we'd have on our hands if the |
Oh, I'm not pushing for core Autofac changes. If it's possible to limit it to this package, awesome. I'm just trying to keep track of thoughts as they pop up. |
Same here, I'm just entertaining the thought and trying to understand how weird it'd be when resolution of a keyed service in |
Might be... a little weird. Maybe not enough to matter? But could be a sort of odd gotcha if someone is trying to use Autofac semantics to resolve an |
There may be a problem, when third party library uses this feature to inject it's services into container, or resolve them with |
We recently upgraded both Orleans 8.0 and Abp Framework. While Abp uses Autofac, Orleans 8.0 uses KeyedService, which results in a startup error: System.InvalidOperationException: This service descriptor is keyed. Could you please fix this issue as soon as possible or provide a temporary solution to resolve it? |
@tillig, a note on registration order and collections for keyed services; the collection source in Autofac sorts by the original registration order, so I'd expect the order of generated any-key-sourced services to match, provided it copies the metadata over from the original registration. I've spent the morning working on the keyed services branch, and all the specification tests now pass on the Summary of changes from your base @tillig are as follows:
Can you check the changes over and that they make sense and I haven't missed anything? |
That's awesome! I'll look it over in the next couple days. |
@alistairjevans This looks great. Thanks for getting it over the line. I'm glad I wasn't too far off with the answer, but clearly had some... uh... cognitive challenges stopping it from just getting completed. And it's totally isolated from Autofac core, so that's super sweet. I removed the temporary debuggable tests fixture and updated the dependencies to latest releases. Here's how I'd like to propose release here:
If that all sounds good, I can probably get it done tomorrow. |
Sounds good, happy with the major semver change. Can I ask for that PR though for future paperwork/tie-to-issue reasons? I can approve and merge before you wake up tomorrow. |
I'll PR it with everything but the Autofac core dependency upgrade. I don't have time right now to shepherd that through, but I could do it tomorrow. |
@alistairjevans , @tillig , I just wanted to say you're amazing, and I'm sorry I wasn't able to help even while I decided to speak up for that. |
@srogovtsev no worries, mate, we appreciate any help we can get and you've thrown in some great contributions in the past. I'm just glad we got this over the line! |
PR approved and merged. I'll do the core Autofac release and subsequent AEDI update/release tomorrow. |
Autofac 8.0.0 and Autofac.Extensions.DependencyInjection 9.0.0 are published. |
Just came across a Twitter post from David Fowler. Looks like the next version of the dotnet SP will support keyed services.
https://twitter.com/davidfowl/status/1683956501570879489?t=EzKZPsabAvVngUAZeCXUAA&s=19
Not sure how it works under the hood but looks to me like it's an entire new mechanism which might need to be supported here.
If you already looked into it and know it will work, please close.
The text was updated successfully, but these errors were encountered: