-
Notifications
You must be signed in to change notification settings - Fork 7
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
.net 8.0 support #36
base: master
Are you sure you want to change the base?
.net 8.0 support #36
Conversation
I gave some thoughts to the missing features:
So instead of just looking for specific interfaces, like it does now: // In ConstructorExpressionCreator.ProcessImportAttributes()
var importAttribute = (IImportAttribute)parameter.GetCustomAttributes()?.FirstOrDefault(a => a is IImportAttribute);
if (importAttribute != null)
{
var info = importAttribute.ProvideImportInfo(parameter.ParameterType, parameter.Name);
// ...
} It would have an additional layer that consider registered adapters: // In Grace
private Dictionary<Type, Func<Attribute, ParameterInfo, ImportAttributeInfo>> adaptors = new();
public void RegisterIImportAttribute<A>(Func<Attribute, ParameterInfo, ImportAttributeInfo> adaptor)
where A: Attribute
=> adaptors.Add(typeof(A), adaptor);
public ImportAttributeInfo? GetImportAttributeInfo(ParameterInfo parameter)
{
foreach (var attr in parameter.GetCustomAttributes())
{
if (attr is IImportAttribute i) return i.ProvideImportInfo(parameter.ParameterType, parameter.Name);
if (adaptors.TryGet(attr.GetType(), out var adaptor)) return adaptor(attr, parameter);
}
return null;
}
// In Grace.DependecyInjection.Extensions
RegisterIImportAttribute<FromKeyedServiceAttribute>((attr, _) =>
new ImportAttributeInfo
{
ImportKey = ((FromKeyedServiceAttribute)attr).Key,
IsRequired = true,
}; |
@jods4 thank you so much for taking a look at this, between work and family life I haven't been able to do any OSS development this year. My hope is in the coming year things calm down at work and I'm able to find some time for Grace and my other projects. I think your idea of registering adapters makes a lot of sense. I can't work on it for the next two weeks but I'm hoping to have some time Christmas week (I have a presentation to put together as well as an on call shift coming up). |
@ipjohnson No worry, I'll try to give a hand. Registering attribute adapters is something I should be able to PR. Quick question: how do you usually proceed when a development in one library (this one) depends on a new release of Grace core? |
More thoughts on missing Grace features for .net 8: AnyKey I'm thinking of exposing a static
Service Key I'm thinking of encoding this with another well-known key: |
|
I have completed the integration of MS DI thanks to the new features in ipjohnson/Grace#314 and I added the new Keyed specification tests from MS. EDIT I built it locally and ran the tests. The source code of MS keyed DI tests is here: One thing I have already noticed that will require important changes in Grace: |
MS DI 8.0 is a direct dependency and it's usable on .net 4.6.2
Add global configuration in Directory.Build.props
I have bootstrapped the work to support keyed services in .net 8.0.
Please note that this is incomplete as there are new features that I'm not sure how to best add to Grace:
ServiceDescriptor
has new members (IsKeyedService
and co.), to register keyed services.GraceServiceProvider
should implementIKeyedServiceProvider
, an extension ofIServiceProvider
.It looks like .net still always injects
IServiceProvider
but then checks ifIKeyedServiceProvider
is implemented when keyed services are requested. Extension methodsGetKeyedService
are defined onIServiceProvider
based on this principle.ServiceProviderIsServiceImpl
should implement extended interfaceIServiceProviderIsKeyedService
.Skimming .net source code, it looks like this is downcasted from
IServiceProviderIsService
butIServiceProviderIsKeyedService
is also considered a legit exported type, so I exported this interface explicitly, too.FromKeyedServiceAttribute
I feel like this BCL attribute needs to be understood by Grace, as it indicates the imported key when resolving services that were registered through BCLServiceCollection
apis.Not sure what the best code is here: I guess in
GraceRegistration.Register()
we need to look at ctor parameters to identify which ones have[FromKeyedServices]
and configure the strategy accordingly?Also wondering how this interacts with auto-registration: can any type not going through
GraceRegistration.Register()
use[FromKeyedServices]
? That feels more robust but then I'm not sure how to teach core Grace about this attribute in a decoupled fashion.KeyedService.AnyKey
This is a well-known singleton, that when used during registration (i.e.container.AddKeyedService<T>(KeyedService.AnyKey)
) indicates that this registration should match all keys during resolution. I think Grace has no such feature at the moment.My understanding of this new feature is that when locating one instance, matching keys have priority. Then if no such key exist then
AnyKey
registrations are considered. When locating all instances (e.g.IEnumerable<T>
), then both matching keys andAnyKey
must be returned.It might seem weird to resolve a registration regardless of its key, but when you combine this with the next feature
ServiceKeyAttribute
, it opens up interesting use-cases as the ctor can be aware of the key being created.Note that
AnyKey
must not be conflated withnull
. .net considersnull
as a non-keyed registration. Also when doing a non-keyedLocate<T>()
,AnyKey
registrations must NOT be included.ServiceKeyAttribute
This is another BCL attribute that Grace needs to know about: it can be used on astring
ctor parameter and the parameter must receive the service key being created. This works nicely in combination withAnyKey
.