1

I am developing a NuGet package which contains shared code for various ASP.NET Core projects. I am planning to use the strategy pattern to solve the same problem in a few different ways. So there will be a few different implementations of a common interface. See - https://deviq.com/design-patterns/strategy-pattern

My question is - should the consumers of this package select the specific strategy they wish to utilize via a registration with the IoC container? I know that some NuGet packages just use static methods (e.g. JsonConvert.DeserializeObject), but I would like to avoid this since I have multiple, valid, differing implementations, and I would like the consumers of the package to be able to choose between them.

3
  • 2
    Many popular .NET libraries provide extension methods for IServiceCollection (and other containers) which allow configuration to be provided/wired on app startup. For example, EasyNetQ (a wrapper library around RabbitMQ.Client) includes an extension method which can register EasyNetQ with the DI container: github.com/EasyNetQ/EasyNetQ/blob/develop/Source/… Aug 26, 2022 at 7:43
  • I don't understand why this question is in any way NuGet related. Wouldn't it be the same if one uses a different distribution technology (like a download link on some website)? So would it not be clearer to strip out NuGet completely out of this question, and just ask about a resuable library?
    – Doc Brown
    Aug 26, 2022 at 8:25
  • @BenCottrell Thanks so much for pointing that out to me! Very helpful example. :)
    – Treker
    Sep 2, 2022 at 18:02

3 Answers 3

3

Your library should be stand-alone. It should work without any kind of dependency injection container, because that is an implementation detail of the application and a library should not care.

I think many people would appreciate if instead of an example in your docs of how to use your library with a specific dependency injection container, you would simply publish another package, using both your stand-alone package and a specific DI technology and providing helper functions that do all the wiring.

That way, if I do use for example the ServiceCollection that is default for most apps, I have an easy way to do so with your additional package, but if I use another mechanism or maybe even none at all, I can still include your package and don't have to worry about all the dependencies you bring that I explicitely do not want to use.

That is a common pattern.

Let's say you name your package "MyCoolAlgorithm" then you can have a package "MyCoolAlgorithm.Unity" or "MyCoolAlgorithm.ServiceCollection" or any other container technology you want to provide for people to make it easier using you library with that technology.

1
  • Very helpful answer. Thank you!
    – Treker
    Aug 26, 2022 at 15:22
1

I have multiple, valid, differing implementations, and I would like the consumers of the package to be able to choose between them.

Good.

should the consumers of this package select the specific strategy they wish to utilize via a registration with the IoC container?

What IoC container? I don't need no stinking container to use NuGet, the Strategy Pattern, or choose my own "differing implementations".

Oh I see the problem. You need a better example of the Strategy Pattern. That's one in C# that actually puts the news high up the call stack where they belong.

When accessing them from a library they aren't much different:

enter image description here

Notice how that looks a bit like the Strategy Pattern diagram? This is from a fairly popular library.

enter image description here

Any one of those ISomething types can stand in for Strategy. The grey boxes can stand in for the ConcreteStrategies. Only thing missing is the Context. You can leave that as an exercise for your user. Or maybe you have something in mind for Context. Fine, make the library user build one of these concrete types and hand it to you.

The important thing about the Strategy Pattern is that you don't have to know at compile time what you're using. It certainly isn't what IoC container someone talked you into using.

1
  • Thank you for the helpful answer! I appreciate it. :)
    – Treker
    Aug 26, 2022 at 15:55
0

Why do you have multiple strategies? There's two options here:

A One is universally superior to the others.

In this case, you can safely discard all the others and use the superior one by default.

B They each have their own strengths and weaknesses.

This is a justification to keep multiple strategies. Given the different pros and cons of each strategy, your consumer will want to choose the strategy that best fits their use case.

I would suggest making this choice optional. Provide a default implementation, but make it overridable when a consumer so chooses.

1
  • Obviously, since I am choosing to keep multiple strategies, "B" is the case in my scenario. I am asking about HOW the consumer should choose the strategy they want. Via DI or just choosing a class.
    – Treker
    Aug 26, 2022 at 15:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.