question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

DI component registration order

See original GitHub issue

Current behavior in RegisterBus:

serviceRegister.RegisterDefaultServices();
registerServices(serviceRegister);

Also note this comment (which IS NOT true at least for Microsoft.Extensions.DependencyInjection): изображение

I will explain the problem using Microsoft.Extensions.DependencyInjection as an example.

All Register methods use AddXXX (instead TryAddXXX). So the problems are:

  1. If I register some EasyNetQ component inside IServiceCollection before RegisterEasyNetQ then RegisterDefaultServices appends new registration to list and it “overwrites” my one.
  2. If I register EasyNetQ component after RegisterEasyNetQ then my registration wins (good!) but it contradicts aforementioned xmldoc comment. Besides, I still have doubled registrations in IServiceCollection.
  3. There may be side effects when dependencies are injected as IEnumerable<IXXX>. Then both components will be used - one added by RegisterDefaultServices and one added by user delegate. To avoid this, you need to do some Replace call, but IServiceRegister does not provide such API as well as it does not provide the ability to check current registrations.

I believe that it is necessary to refactor the behavior responsible for DI.

  1. Change IServiceRegister.Register behavior to TryRegister or provide additional methods, maybe extension methods to keep IServiceRegister thin.
  2. Change implementation of DefaultServicesRegistration.RegisterDefaultServices to use TryRegister instead of Register.
  3. Change registration order inside RabbitHutch.RegisterBus - move registerServices(serviceRegister); at the top.
  4. Review all xml comments in classes responsible for DI to not to mislead users.

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:2
  • Comments:26 (24 by maintainers)

github_iconTop GitHub Comments

4reactions
zidadcommented, Apr 29, 2020

I mean this is from LibLog, for me that says it all:

LibLog is now deprecated (see #270).

My recommend course of action for library developers is to use Microsoft.Extensions.Logging.Abstractions as it is now the defacto standard logging interface in the .NET ecosystem.

I think it’s time to move on. EasyNetQ was written to serve a simple set of opinionated use cases, not to be a generic support-everything library. I feel that by using these abstractions it supports the .NET ecosystem the best in an opinionated way, while keeping the library as simple as possible.

I’ve not seen any modern .NET core application that didn’t reference Microsoft.Extensions.DependencyInjection.Abstractions or Microsoft.Extensions.Logging.Abstractions via some dependency.

2reactions
sungam3rcommented, Sep 7, 2020

Well, today I came across a bug where an extra connection to RabbitMQ was created. After an hour of investigating, I realized that the problem was caused by the creation of two bus instances with PersistentConnection inside. First - RabbitAdvancedBus from default registration, second - my MyBus class registered via RegisterEasyNetQ:

.RegisterEasyNetQ("host=localhost:5672;virtualhost=test", reg =>
                {
                    reg.Register<IAdvancedBus, MyBus>(); //  public class MyBus : RabbitAdvancedBus
                })

My use case is service warmup when objects are instantiated from the DI container. In my case, there are two implementations associated with the IAdvancedBus interface due to the fact that the Register method adds registration instead of a replacing it. I believe this confirms the existence of the problem. I’m going to do PR soon.

Read more comments on GitHub >

github_iconTop Results From Across the Web

castle windsor named component registration order
Per the Castle documentation, it states that when more than one components have the same dependency, the first registered component is ...
Read more >
Registration Concepts — Autofac 7.0.0 documentation
You register components with Autofac by creating a ContainerBuilder and ... Build() and will execute in the order of the actual component registrations....
Read more >
Understanding dependency injection
Dependency injection, or DI, is one of the fundamental concepts in Angular. ... When you register a provider at the component level, you...
Read more >
c# - Does anyone have a good DI registration pattern?
How I build my components in a custom way now is by registering them with Ninject, and using methods like WithConstructorArgument() , ...
Read more >
Dependency injection - .NET
Service registration is generally order-independent except when registering multiple implementations of the same type.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found