Comments (9)
@yallie Enjoy vacation, I have moved the thing already and optimized it along the way.
from dryioc.
@lassevk Let's keep this issue open until the IKeyedServiceProvider
and its friends are implemented.
IKeyedServiceProvider
https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.dependencyinjection.ikeyedserviceprovider?view=dotnet-plat-ext-8.0IServiceProviderIsKeyedService
https://learn.microsoft.com/es-es/dotnet/api/microsoft.extensions.dependencyinjection.iserviceprovideriskeyedservice?view=dotnet-plat-ext-8.0FromKeyedServicesAttribute
https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.dependencyinjection.fromkeyedservicesattribute?view=dotnet-plat-ext-8.0KeyedServiceAttribute
https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.dependencyinjection.servicekeyattribute?view=dotnet-plat-ext-8.0- dotnet github issue dotnet/runtime#64427
- more pointed description + differences in
ServiceProvider
dotnet/runtime#64427 (comment)
from dryioc.
Let's address a challenge of the not-uniqueness of the MS.DI keyed services comparing to the uniqueness of DryIoc keyed services.
Solution 1
Create the composite key for the second, third, etc. MS key adding its index into the pair, e.g. "foo", ("foo", 1), ("foo", 2).
Pros:
- For the majority of the cases when user hopefully will use a single key, there will be a parity and backward compatibility between MS and DryIoc.
Cons:
- What happens when a User is resolving the single key in the presence of many? In this approach, we will resolve the first registered service. Or we need to adjust the
SelectLastFactory
rule to search for the duplicate keys. - When resolving the collection of the keyed services by default, DryIoc will return a single service, because the key is unique. It is not clear how to solve this problem
Solution 2
Represent the MS keys as DryIoc metadata
Pros:
- DryIoc metadata is not unique, so multiple services with the same metadata are possible
SelectLastFactory
need to be adjusted to filter based on metadata- Collection wrapper will return multiple filtered services based on the metadata
Cons:
- Discrepancy between two features of MS and DryIoc, there should be a differently named APIs to resolve the services from the MS and from the DryIoc. The documentation should clearly state this fact.
- DryIoc may have the keys in addition to the metadata, which probably will add confusion.
from dryioc.
v8 vs v7 API diff https://www.fuget.org/packages/Microsoft.Extensions.DependencyInjection.Abstractions/8.0.0/lib/netstandard2.1/diff/7.0.0/
from dryioc.
Problems to solve
The multiple same key registrations
DryIoc treats the service key as unique ID for the same service type. So it prevents you with registering the same service type with the same service key.
The main question, should I use the DryIoc metadata then or can
ServiceDecriptor.KeyedImplementationFactory has the key parameter
The type of KeyedImplementationFactory
is Func<IServiceProvider, object?, object>
where the object?
parameter is the key. Specifically, it is not the registration service key but the resolution/injection key, which may differ (e.g. it may be the AnyKey
described below).
Problem is that DryIoc does not supply a service key into the FactoryDelegate
which type is Func<IResolverContext, object>
.
KeyedService.AnyKey
We need to support the KeyedService.AnyKey
to resolve the service with any (not null) service key specified.
Therefore, I will be adding Registrator.AnyServiceKey
on the DryIoc side.
So far, so good. But what is this thing? See the next section for the reveal :-P
[Fact]
public void ResolveKeyedServiceSingletonFactoryWithAnyKeyIgnoreWrongType()
{
var serviceCollection = new ServiceCollection();
serviceCollection.AddKeyedTransient<IService, ServiceWithIntKey>(KeyedService.AnyKey);
var provider = CreateServiceProvider(serviceCollection);
Assert.Null(provider.GetService<IService>());
Assert.NotNull(provider.GetKeyedService<IService>(87));
Assert.ThrowsAny<InvalidOperationException>(() => provider.GetKeyedService<IService>(new object()));
}
ServiceKeyAttribute
Marks the parameter to be injected with the resolution service key as in the following case used by the test above:
internal class ServiceWithIntKey : IService
{
private readonly int _id;
public ServiceWithIntKey([ServiceKey] int id) => _id = id;
}
Moreover, we need to select the appropriate constructor in presence of attribute
In the example Service
we need to select the Constructor with key string id
for the keyed resolution and the default one for the non-keyed one.
internal class Service : IService
{
private readonly string _id;
public Service() => _id = Guid.NewGuid().ToString();
public Service([ServiceKey] string id) => _id = id;
public override string? ToString() => _id;
}
FromKeyedServicesAttribute
internal class OtherService
{
public OtherService(
[FromKeyedServices("service1")] IService service1,
[FromKeyedServices("service2")] IService service2)
{
Service1 = service1;
Service2 = service2;
}
public IService Service1 { get; }
public IService Service2 { get; }
}
from dryioc.
Seems like we are doing the same Key for the same service Type in DryIoc.MefAttributedModel.
For this purpose, MEF has ServiceKeyStore
stores the map from the Key to the all types registered (exported) with this key. And if Type is the same, it increases the number of such registrations and uses this number to augment the service Key and make it unique.
Question, can we use the MEF for MS.DI?...
Probably no, but we may steal the ServiceKeyStore
or better the whole AttributedModel.WithMultipleSameContractNamesSupport
method.
Btw, how to get all non-keyed services in the collection?
//cc @yallie
from dryioc.
Ok, for the last 2 failing tests we need the #618
from dryioc.
@dadhi, sorry, I'm on vacation, have no PC to look into it. Will return next Monday.
Moving the required code from MEF to DtryIoc core seems like a good idea 👍
from dryioc.
done
from dryioc.
Related Issues (20)
- For the conditional singleton or the singleton registered with AnyKey - should we create a new singleton per condition or the resolution key? HOT 1
- Why docs not mentioned with register keyed services base on attributes?
- Possibility to resolve only Non-Keyed services in the collection wrapper
- Add possibility to obtain all service keys for the registered service
- Multiple same service key support mostly for DryIoc.MS.DI though it is already supported in DryIoc.MefAttributedModel
- Move Throw.GetMatchedException to Rules so that extensions may modify it without conflicts HOT 1
- Scoped service decorator HOT 4
- Consistent behavior of a faulty singleton HOT 2
- FactoryType is not forwarded in the RegisterMapping<TService, TRegisteredService> method HOT 1
- IDisposable dependencies does not get disposed when web request ends HOT 5
- Add the HotUsedInstance for fast access to skip all the resolution steps
- Conditional registrations
- MS DI AddKeyed... variant registration fails HOT 8
- Check for mismatch lifestyle scope between service and dependencies HOT 7
- troubleshooting sudden ArgumentException at TryInterpretSingletonAndUnwrapContainerException HOT 3
- [question/feature request] keyed services in delegate resolution HOT 8
- Use default constructor if no registration is found
- Add the global test option to run all tests with WithoutUseInterpretation option
- Feature Request: add global .WithDefaultServiceTypeCondition(Func<Type, bool> condition) method HOT 1
- System.NullReferenceException: Object reference not set to an instance of an object HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from dryioc.