You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Resolving services at runtime by name is a known anti-pattern. That is not to say it isn't a useful feature that solves certain problems. The reason it is an antipattern is that:
resolution of the service with a specific name can fail at runtime if the service with that name has not been registered
the dependencies are not visible in any api surface - and in essence are therefore "hidden" unless you read the internals of the code.
due to above points, there is no way to check / validate that required dependencies are present when the class is constructed - which means it can technically run in an invalid state and hit a runtime exception (back to first point above).
From the perspective of a consumer of this class, it knows there is some dependency on factory function that returns an AnimalService but it's not obvious what name is going to be used when a service is requested, therefore how can it establish how to implement the factory function, unless it can see the internal code in Foo class to work out what names will be used:
varfoo=newFoo((name)=>{// what am I meant to do here? what names will be used? })
So this dribbles down a problem when setting up DI, because the container, cannot tell from its current registrations, whether Foo actually has all of its dependencies met - because resolution of the dependency is based on a string that isn't provided until an invocation at runtime. So the factory function could return NULL or throw an exception if a named service with the name APOWDJAWOJD hasn't been registered in advance - and the container has no way to check for that.
Enter Typed registrations..
varservices=newServiceCollection();services.AddTyped<AnimalService>(types=>{types.AddSingleton();// Will resolve any type used as akey types.AddSingleton<BearService,MyKey>();whenresolved using: MyKey as key,will return BearService
});
Essentially this would do away with magic strings, and instead rely on "marker types" to resolve different registrations of a service.
The thinking behind this, is that it should allow the container to verify if it has a registrations, and solves basically all of the above problems. What's the downside?
You have to choose or create distinct "marker" types to use as keys for registration / resolution.
The text was updated successfully, but these errors were encountered:
Resolving services at runtime by name is a known anti-pattern. That is not to say it isn't a useful feature that solves certain problems. The reason it is an antipattern is that:
Consider this:
From the perspective of a consumer of this class, it knows there is some dependency on factory function that returns an
AnimalService
but it's not obvious what name is going to be used when a service is requested, therefore how can it establish how to implement the factory function, unless it can see the internal code in Foo class to work out what names will be used:So this dribbles down a problem when setting up DI, because the container, cannot tell from its current registrations, whether
Foo
actually has all of its dependencies met - because resolution of the dependency is based on a string that isn't provided until an invocation at runtime. So the factory function could return NULL or throw an exception if a named service with the nameAPOWDJAWOJD
hasn't been registered in advance - and the container has no way to check for that.Enter Typed registrations..
Now you can do this:
Essentially this would do away with magic strings, and instead rely on "marker types" to resolve different registrations of a service.
The thinking behind this, is that it should allow the container to verify if it has a registrations, and solves basically all of the above problems. What's the downside?
The text was updated successfully, but these errors were encountered: