-1

In my C# ASP.NET Core project, I have a class that is currently instantiated using a parameterless constructor. This class is used in hundreds of places throughout the solution.

I now need to refactor the class to support constructor dependency injection by requiring a parameter to be passed in (such as a string or a service). However, due to the large number of existing usages, I can't update all of them immediately.

Using optional constructor parameters is not a viable solution in my case — while it compiles, it causes runtime issues, possibly due to how the framework or dependency injection container handles nulls or default values.

I'm looking for a safe and maintainable way to introduce the new required constructor dependency without breaking existing code. I'm also trying to follow best practices and move toward dependency injection.

So far, I’ve considered options like adding an overloaded constructor, using a base class for shared logic, applying a factory or builder pattern, and marking the old constructor as obsolete to track usage.

What approach would you recommend to transition this class to constructor-based dependency injection without breaking the current system?

4
  • 3
    How about using a factory class. Check out the Factory Design Pattern. Commented Aug 4 at 7:50
  • 2
    So far, I’ve considered options like adding an overloaded constructor - That sounds like a reasonable approach; you should try that one! Then you can piecemeal change things and eventually remove the default ctor. Commented Aug 4 at 7:54
  • 3
    "while it compiles, it causes runtime issues," - so, you gave up on it or still investigating? Commented Aug 4 at 7:55
  • 1
    When you register this class in your DI, you can provide a factory method. So if your DI has trouble handling optional ctor params, you could easily do this manually. Commented Aug 4 at 7:59

1 Answer 1

4

The option I would recommend is to just overload the constructor. Create one constructor that accepts all required parameters, and update the other to call that one, so you can be sure the code in the main constructor is always called.

If you are using microsofts DI container you may need to add [ActivatorUtilitiesConstructor] to the constructor you want the dependency injection to use. Other DI containers may use different attributes or different ways to specify the constructor to use.

The main case I would consider a factory method or class would be if you need to create instances on demand. If you do not need that I would stick to regular constructors.

marking the old constructor as obsolete to track usage

Marking it as obsolete will generate warnings, and I recommend to treat warnings as errors by default, since it drastically reduces the risk of missing relevant warnings. If you can, just fix it up front, and if that is to much work, at least add pragmas to ignore the warning in existing usage, so you only get warnings if it is used in new code. Or perhaps just add some comments to describe the correct usage.

using a base class for shared logic

This seem like a separate issue, but the standard recommendation is composition over inheritance. I.e. move shared logic to a separate class instead.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.