Master the Keyed Services in ASP.NET Core Dependency Injection

Поделиться
HTML-код
  • Опубликовано: 4 дек 2024

Комментарии •

  • @jhdk356
    @jhdk356 4 часа назад +1

    Autofac has the same feature, but apart from using attributes within the classed, it is also possible to instead specify which key to resolve for a particular class when registering that class. That way, it becomes up to the application architect wiring up the dependency injection to decide what keyed dependencies are meant for which classes, while the classes themselves remain ignorant of this. I usually prefer this approach, instead of having the information leak into the classes, although I like this 'hack' presented here of specifying the class type itself as key.

    • @zoran-horvat
      @zoran-horvat  4 часа назад +1

      @@jhdk356 I also hoped ASP.NET Core DI would take that route, but it seems they didn't choose it.

  • @JSmart523
    @JSmart523 3 часа назад

    I needed this _today_. Thank you!
    If you're curious, my use case is an ETL engine with classes for inputs (like input files but could be anything that results in IEnumerable of data to be provessed) with functionality that includes archiving the source data for audit and troubleshooting needs when it pulls the data, and another set of classes with a `ProcessAndUpload` method that takes the IEnumerable of input data and does stuff. I had separated duties like this so that each input can be read only once and distributed to several different destination handlers that each input class receives via dependency injection. Today, the destination classes are provided via DI, each destination class hardcoded into the input classes that use them. When I switch my code tomorrow, thanks to you, each input class won't need to hardcode the destination handlers by name, the input classes can receive an enumerable of destination handlers through dependency injection of services keyed per input class.

  • @W1ese1
    @W1ese1 16 часов назад +1

    Finally the day has come where I learned nothing from one of your videos!
    It's a great introduction to Keyed Services and would recommend this video to anyone interested in the topic!

    • @zoran-horvat
      @zoran-horvat  16 часов назад +2

      @@W1ese1 Nice! But did you know you can use typeof operator to create the service key?

    • @jarek_rudnik
      @jarek_rudnik 13 часов назад +2

      @@zoran-horvat I for example was not aware of this. Additional benefit is that this will work in .NET 8 while Enum approach as you mentioned was fix recently in .NET 9. Great content!

  • @krajekdev
    @krajekdev 17 часов назад +4

    Good material, thanks. Could you discuss shortly the obvious alternative, I mean using a separate interface per usage so for example `IRecommendationBookFormatter', 'IListItemBookFormatter` etc. Details of the names does not matter, just an example. Wouldn't it be more natural to segregate interfaces instead of unifying them just to throw additional layer of abstraction on top of it?

    • @zoran-horvat
      @zoran-horvat  16 часов назад +1

      @@krajekdev That doesn't resolve the underlying problem that the consuming service now knows which kind of other service it requires. You will observe that the endpoint would possess the same knowledge as it did when it used the attribute to specify the specific service it needs. The keyed services only make the registration somewhat shorter.

    • @KristianVidemarkParkov
      @KristianVidemarkParkov 8 часов назад +1

      @zoran-horvat It knows what service it requires, yes, but with a keyed service it only hints to what it wants, but won’t say it clearly. It’s inelegant.

    • @zoran-horvat
      @zoran-horvat  7 часов назад

      @@KristianVidemarkParkov How would you configure that in a config file? What makes fixing the services at compile time elegant?

    • @KristianVidemarkParkov
      @KristianVidemarkParkov 7 часов назад

      The problem is it is asking for an IService, but it doesn’t really mean it. It actually wants an ISpecializedService, so while the two services have the same shape, they are not truly interchangeable. I would solve it with a subtype.

    • @zoran-horvat
      @zoran-horvat  7 часов назад

      @@KristianVidemarkParkov How do you implement concrete classes, then?

  • @luc9volts
    @luc9volts 13 часов назад +1

    Nice tip. Thanks

  • @Tesfamichael.G
    @Tesfamichael.G 14 часов назад

    Great Lesson!

  • @johncerpa3782
    @johncerpa3782 10 часов назад +1

    Great video!

  • @KristianVidemarkParkov
    @KristianVidemarkParkov 8 часов назад +1

    I’m not crazy about keyed services. It asks the consumer to define what to expect, which seems to lessen the value of the injection, and is akin to a service locator. At that point, maybe just let the consumer decide on the implementation it needs?

    • @zoran-horvat
      @zoran-horvat  6 часов назад +1

      You cannot let the consumer decide if the decision depends on information the consumer does not possess. For example, consider deployment-dependent assignment of services.

  • @istovall2624
    @istovall2624 15 часов назад

    Did I miss something, I usually use service locator pattern, what's the trade offs for this keyed service vs locator pattern?

    • @doublebass120
      @doublebass120 13 часов назад +1

      To set up a unit test, you would need to register the service in your IOC container. With this approach, i don’t think that’s necessary. Makes the test cleaner.

  • @ДмитрийКондратенко-б5ь

    I think I missed something at the end of the video when page model received a sequence of formatter services. How can page choose the proper one from this sequence? If the answer is selecting only one service by its specific type then looks like we get leaking information to the page model class again because it should know what concrete type of formatter it's needed. So, this my assumption is incorrect but I still don't understand what is the correct way to work with IEnumerable inside the consumer class. If Zoran could show this refactoring in the video for the page model class it would be clearly to understand.

    • @zoran-horvat
      @zoran-horvat  4 часа назад +1

      @@ДмитрийКондратенко-б5ь The using class does not make a choice. This concept is meant for the classes that need to call multiple services to complete their work, so you can configure multiple instances of that service interface.

    • @ДмитрийКондратенко-б5ь
      @ДмитрийКондратенко-б5ь 4 часа назад +1

      ​​​@@zoran-horvat, oh, I got it. This approach only for consumer that needs to have many formatters and apply them as a chain. Thanks for explanation. I didn't hear this point in the video so it confused me.

  • @AK-vx4dy
    @AK-vx4dy 15 часов назад

    @12:00 Great material, but depending on order of occurence declaration in code i can not praise.

    • @zoran-horvat
      @zoran-horvat  15 часов назад +1

      @@AK-vx4dy But the class doesn't depend on the order. It executes the actions in the order given, which it doesn't know.

    • @AK-vx4dy
      @AK-vx4dy 4 часа назад

      @@zoran-horvat To format thing differently, class gets IEnumeable of formatiing services, then must have a way to select one or another, so must select first, second, etc. or have some konwledge about specific formater types or they have some abstract mechanism to query who they are or some attributes of them.

    • @zoran-horvat
      @zoran-horvat  4 часа назад +1

      @AK-vx4dy You are missing the point. The class doesn't have any special knowledge of how any of the services differs from the others. It knows nothing about them past what their interface says.
      Don't you see that in the demo, too? The endpoint uses all services uniformly.

    • @AK-vx4dy
      @AK-vx4dy 2 часа назад

      @@zoran-horvat I'm talking about part when you show possiblity of taking IEnumerable and injecting more that one formater without a key, model must have some assumption that for example for left column uses first element and for right second element from this IEnumerable, so order of declaration decides or model have some knowledge about formaters.

  • @marcobaccaro
    @marcobaccaro 12 часов назад

    Good content. You might know that using the class type as a key restricts DI registration to one class-it's confusing from the consumption standpoint. Registering multiple classes with a single key is fine since the consumer doesn't have to know the types in the Enumerable ;)

    • @zoran-horvat
      @zoran-horvat  12 часов назад +2

      @@marcobaccaro Yes, that is what I wanted to demonstrate. You can group services by features, and then configure a different choice for one page only.

  • @andreybiryulin7207
    @andreybiryulin7207 19 часов назад

    But now your domain depends on DI framework that is used and whether it supports that FromKeyedServiceAttribute or not. It is similar pain how EF mapping via attributes used to be and nowadays everyone is using code first mapping.

    • @Mig440
      @Mig440 19 часов назад

      How is the domain dependent on the keyedservices here exactly? The interface registered in DI does not know about the keyed services attribute so you must mean something different is dependent on the keyedservices attribute

    • @andreybiryulin7207
      @andreybiryulin7207 19 часов назад +1

      @ your domain ctor code uses FromKeyedServiceAttribute and relies that DI framework supports it to understand what to inject

    • @zoran-horvat
      @zoran-horvat  18 часов назад +8

      @@andreybiryulin7207 It is the endpoint/controller that uses the FromKeyedServices attribute, and it belongs to the outermost services layer, which is already tightly bound to ASP.NET Core in all kinds of ways. Nothing below the services layer, and certainly not the domain, knows anything about how the injection is performed. Therefore, the domain model does not depend on the DI framework.