Wanted: Beta Testers
# Jun 29, 2015 by StevenWith Simple Injector 3 we are breaking with the past and working hard to simplify the API to better represent our ideals and, of course, the name of our library. This means that we are introducing breaking changes in v3 that will undoubtedly impact any developer migrating from v2.
The driver for making these breaking changes is that areas of the API have evolved over time and in so doing have grown confusing (e.g. RegisterOpenGeneric
and RegisterManyForOpenGeneric
). In the pursuit of keeping Simple Injector simple we felt obligated to improve the consistency of the API. These decisions have not been taken lightly because we hate breaking your code. Our driving force is, however, a simpler Simple Injector for everyone.
We are doing our best to make the transition as seamless as possible and we need feedback on this effort. We are looking for Simple Injector users to test the beta of Simple Injector 3 and tell us what they think.
If you can help then please upgrade your NuGet packages to 3.0.0-beta4 and try to compile your code (it will probably fail!). Our main strategy is to guide users with obsolete messages that should be presented as descriptive compiler errors. Once you have fixed any errors please call Verify() on your container, (as you are hopefully already doing) and test your application to ensure everything resolves as expected. To discuss any element of beta testing please join us on gitter. We would usually expect the upgrade process to take no more than a half hour.
Please note that we don’t expect you to do our testing for us. Simple Injector has an extensive suite of unit tests and we don’t expect to have introduced many new bugs.
Here’s a list of the most prominent breaking changes we are introducing:
- Calling
Verify()
will now automatically diagnose the container’s configuration for common configuration mistakes and exceptions will be thrown. We felt that not enough developers were explicitly callingAnalyzer.Analyze()
to check for diagnostic warnings, leading to a common source of bugs. So we decided to integrate this into Verification in the hope that this will guide our users to the pit of success. The old Verification behaviour can be triggered by callingVerify(VerificationOption.VerifyOnly)
. - Even if you don’t call
Verify()
, the v3 the container will always check for lifestyle mismatches when resolving an instance and will throw an exception if there is a mismatch in the object graph. This more strict behaviour can be suppressed globally but (for obvious reasons) we advise against doing so. - The
RegisterSingle
methods have been renamed toRegisterSingleton
as we felt there was some ambiguity in the nameRegisterSingle
, especially in combination with methods likeRegisterAll
,RegisterCollection
andRegisterManyForOpenGeneric
. We considered removing these method completely, but the benefits of doing so did not compare favourably to the pain of fixing this as a breaking change. - The
RegisterAll
methods have been renamed toRegisterCollection
. Just as with theRegisterSingle
methods, new developers experienced confusion in their naming. The new name expresses more clearly what the methods do. - The
RegisterManyForOpenGeneric
extension methods from theSimpleInjector.Extensions
namespace have been replaced with newRegister
andRegisterCollection
overloads on theContainer
. When doing one-to-one mappings,Register(Type, IEnumerable<Assembly>)
can be used, and when registering collectionsRegisterCollection(Type, IEnumerable<Assembly>)
can be used. - The
RegisterSingleDecorator
extension methods have been removed. Decorators can be registered by callingRegisterDecorator
while supplying theLifestyle.Singleton
. - The
RegisterOpenGeneric
extension methods have been removed. TheContainer.Register
methods have been extended to accept open generic types. This removes the superficial difference between the registration of open generic types and other registrations. (This difference originally had a technical background, but we allowed the internal difference to effect the user experience.) Do note that there is a behavioural difference betweenRegisterOpenGeneric
andContainer.Register
.RegisterOpenGeneric
registers each generic type as fall-back, which means it will apply that type if no other registration exists for that type. Conversely,Container.Register
will not register a fall-back, it will, instead, test for overlapping registrations. If the fall-back behaviour is required, the newRegisterConditional
methods can be used. The newRegisterConditional
methods allow supplying a delegate that allows signaling a registration as fall-back registration. IConstructorVerificationBehavior
andIConstructorVerificationBehavior
have been merged and replaced withIDependencyInjectionBehavior
.
In the majority of cases the compiler error messages should guide you through the migration. If you find a scenario that is unclear or it takes time to figure out please let us know. We want to make the migration as seamless as possible.
Besides the above list of breaking changes, we have some compelling new features that may be of interest:
- A
Lifestyle.Scoped
property was added to simplify registration of scoped lifestyles, since in most applications you would typically only use one specific scoped lifestyle. You can now useRegister<IService, Impl>(Lifestyle.Scoped)
instead of having to callRegisterPerWebRequest<IService, Impl>()
for example. This also simplifies reuse in your composition root, when the same configuration is reused over multiple application types (such as MVC and WCF). - As noted above
RegisterConditional
methods are added to theContainer
to allow registering types based on contextual information such as information about the consumer in which they are injected. - Batch registration made easier by adding overloads of the
Register
method that accept either a collection of types or a collection of assemblies. - As explained above, the
Register
methods now accept open generic types. - The container now implements
IDisposable
. This allows cached singletons to be disposed when the container gets disposed. RegisterCollection(Type, IEnumerable<Registration>)
now accepts open generic service types as well.