Giter Site home page Giter Site logo

Comments (9)

dadhi avatar dadhi commented on May 24, 2024 1

@yallie Enjoy vacation, I have moved the thing already and optimized it along the way.

from dryioc.

dadhi avatar dadhi commented on May 24, 2024

@lassevk Let's keep this issue open until the IKeyedServiceProvider and its friends are implemented.

from dryioc.

dadhi avatar dadhi commented on May 24, 2024

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.

dadhi avatar dadhi commented on May 24, 2024

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.

dadhi avatar dadhi commented on May 24, 2024

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.

dadhi avatar dadhi commented on May 24, 2024

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.

dadhi avatar dadhi commented on May 24, 2024

Ok, for the last 2 failing tests we need the #618

from dryioc.

yallie avatar yallie commented on May 24, 2024

@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.

dadhi avatar dadhi commented on May 24, 2024

done

from dryioc.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.