Releases: unitycontainer/unity
5.5.1.415
New features
- IContainerContext - new official UnityContainer face for internal operations
- IRegisterTypeStrategy - new interface allowing strategies to be part of registration and add policies as required.
- SingletonLifetimeManager - new globally unique lifetime manager.
Breaking changes
- ITypeInterceptionPolicy - has been optimized to resolve via IUnityContainer instead of IBuilderContext
- IInterceptionBehaviorsPolicy - has been optimized to resolve via IUnityContainer instead of IBuilderContext
Bug fixes
- #177 - Fixed rare condition where setting type interceptor on registration instead of resolving singleton instantiates new instance for each resolution.
5.5.0.394
This release has a lot of modifications and breaking changes. The changes are required to enable new features and optimizations.
Unity.Abstractions v3.0.0 has been released
Breaking changes
-
#6
IUnityContainer.IsRegistered
. Finally added built-in, 'fast' mechanism to check if type is registeredbool IsRegistered(...);
(High impact) -
#22 Replaced all references to
NamedTypeBuildKey
withINamedType
. (Low impact) -
#23 Renamed IDependencyResolverPolicy into IResolverPolicy (Affects resolution of overridden dependencies)
-
#27 Merged FactoryDelegateBuildPlanPolicy with InjectionConstructor (Low impact)
-
#30 Added Parent reference to IBuilderContext (New feature)
-
#31 Added return type and extra argument to PreBuildUp and PostBuildUp (High impact for custom strategy implementations)
5.4.0.379
This release is primarily addresses extending of strategy chains to support multiple types of strategies. These changes are required to implement custom Property, Method, and Constructor selectors.
Breaking changes
-
#20 A non generic interface
IStagedStrategyChain
has been retired. Generic interfaceIStagedStrategyChain<TStageEnum>
has been modified to accept strategy type argument.StagedStrategyChain
has been modified to allow different strategy types.
In order to iterate through strategies just use IEnumerable<...>. -
#21 IPolicyList no longer accepts
object
as a Build Key. Legacy API was moved to Extension Methods implementation.
Semantic Versioning
This release breaks several interfaces and should have been released as v3.0.0. It has been long weekend of coding...
5.3.2.353
5.3.0.313
Due to this bug fix sequence of steps during building of objects has changed. Previously strategies were called in this order:
...
TypeMapping,
Lifetime,
PreCreation,
...
Now Lifetime and TypeMapping where reversed and Lifetime is called first. Here is the modified UnityBuildStage
public enum UnityBuildStage
{
/// <summary>
/// First stage. By default, nothing happens here.
/// </summary>
Setup,
/// <summary>
/// Third stage. lifetime managers are checked here,
/// and if they're available the rest of the pipeline is skipped.
/// </summary>
Lifetime,
/// <summary>
/// Second stage. Type mapping occurs here.
/// </summary>
TypeMapping,
/// <summary>
/// Fourth stage. Reflection over constructors, properties, etc. is
/// performed here.
/// </summary>
PreCreation,
/// <summary>
/// Fifth stage. Instance creation happens here.
/// </summary>
Creation,
/// <summary>
/// Sixth stage. Property sets and method injection happens here.
/// </summary>
Initialization,
/// <summary>
/// Seventh and final stage. By default, nothing happens here.
/// </summary>
PostInitialization
}
This change should not affect casual users of the container. Developers of Extensions that rely on this sequence of stages should verify if the change might have broken the extension.
5.2.1.311
Important
This release changes how types are registered.
Bug fix
This release is a part of a fix of longest running Unity bug. The problem it addresses is with registrations affecting each other when new registration is the same Type as previously registered mapping.
Following code explains the problem:
IUnityContainer uc = new UnityContainer();
uc.RegisterType<ILogger, MockLogger>(new ContainerControlledLifetimeManager());
ILogger logger = uc.Resolve<ILogger>();
Assert.IsNotNull(logger);
Assert.AreSame(uc.Resolve<ILogger>(), logger); <-- Resolves Singleton as it should
uc.RegisterType<MockLogger>(new TransientLifetimeManager()); <-- Here is the problem
Assert.AreSame(uc.Resolve<ILogger>(), logger); <-- Resolves new MockLogger and fails
The issue is described here
Impact on existing code
To demonstrate impact on existing code please look at this example:
container.RegisterType<ISomething, Something>(new ContainerControlledLifetimeManager());
var a = container.Resolve<Something>();
var b = container.Resolve<ISomething>();
Assert.AreNotSame(a, b);
Due to the this bug resolving a and b returned the same result because ContainerControlledLifetimeManager
would be applied to ToType instead of FromType as it should. In other words it would be applied to Something
instead of ISomething
.
This fix corrects this behavior so only ISomething
registers with ContainerControlledLifetimeManager
and resolution of Something
type will use transient manager.
You could replicate behavior of Unity before this bug fix by simply registering mapped type with proper lifetime manager:
container.RegisterType<Something>(new ContainerControlledLifetimeManager());
For more information see: #35, 163, #164, #165, #170, #177
More strict use of InjectionFactory
This form of registration used to work for registering interface with InjectionFactory
but it is no longer allowed.
RegisterType<IService, Service>(new InjectionFactory(c => new Service()));
As written, this code registers both: a mapping between IService
and Service
and between IService
and InjectionFactory
. These two are mutually exclusive and create ambiguity which Unity can not resolve.
It should be either one of these but not both:
RegisterType<IService, Service>();
RegisterType<IService>(new InjectionFactory(c => new Service()));
Upgrading to Release v5.2.1
This release fundamentally changes how types are registered with Unity. The rationale behind this change is this issue.
The problem
To explain the problem please look at this example. Prior to this release registering singleton ILogger
service like this:
container.RegisterType<ILogger, MockLogger>(new ContainerControlledLifetimeManager(), new InjectionConstructor());
would create two registrations:
- A mapping between
ILogger
toMockLogger
- A singleton registration for
MockLogger
with default constructor.
Calling container.Resolve<ILogger>()
resolves singleton instance of MockLogger as expected, and resolving type MockLogger container.Resolve<MockLogger>()
would resolve the same instance of MockLogger. Both ContainerControlledLifetimeManager and InjectionConstructor would be associated with MockLogger registration.
Suppose you want to resolve a new MockLogger whenever it is resolved directly like this container.Resolve<MockLogger>()
. To do so you would create another registration just for the MockLogger:
container.RegisterType<MockLogger>(new TransientLifetimeManager());
So, now when you call container.Resolve<MockLogger>()
it resolves new instance of the MockLogger class and uses constructor with longest list of parameters. All is well and as expected. But now if you try to resolve container.Resolve<ILogger>()
it is no longer returns singleton instance of the MockLogger. Now it also returns new MockLogger created with constructor with longest list of parameters.
The subsequent registration overwritten all information associated with ILogger
.
The solution
Release 5.2.1 fixes this behavior. Now all information passed to Unity during registration is stored with FromType
instead of ToType
. So registering type like this:
container.RegisterType<ILogger, MockLogger>(new ContainerControlledLifetimeManager(), new InjectionConstructor());
creates just one registration ILogger
and associates LifetimeManager and all provided InjectionMemebers with it. At this point MockLogger is still unregistered.
So, think about it as a RegisteredType
and MappedTo
type. If you look at initial example:
container.RegisterType<ILogger, MockLogger>(new ContainerControlledLifetimeManager());
ILogger
- is a registered type and ContainerControlledLifetimeManager is associated with this type, as well as any InjectionMembers
you provide during registration.
Breaking changes
This release breaks a lot of registrations. Anything relaying on TypeTo being registered in mappings will fail. For example:
container.RegisterType<ILogger, MockLogger>(new ContainerControlledLifetimeManager());
Assert.AreSame( container.Resolve<ILogger>(), container.Resolve<MockLogger>()) <-- Will fail now
This could be easily fixed by slightly modifying how types are registered. If you want TypeTo to be available independently you could register it like this:
container.RegisterType<MockLogger>(new ContainerControlledLifetimeManager());
container.RegisterType<ILogger, MockLogger>();
Assert.AreSame( container.Resolve<ILogger>(), container.Resolve<MockLogger>()) <-- Passes
This applies to anything you registering with the type: factories, injection members, interceptors, etc.
Fixing
With some creative searching and sorting these breaking registrations could be identified statically, without running the code. The key is to look for registrations with same TypeTo type. If you see multiple registrations registering same type as implementation type and at least one of them has non transient lifetime it is a good indicator that it might fail after update:
container.RegisterType<ILogger, Logger>(new ContainerControlledLifetimeManager());
...
container.RegisterType<IOtherLogger, Logger>();
To fix just add individual registration for implementation type with proper lifetime manager like so:
container.RegisterType<Logger>(new ContainerControlledLifetimeManager());
...
container.RegisterType<ILogger, Logger>();
...
container.RegisterType<IOtherLogger, Logger>();
Make sure it is registered before other mappings.
Cleanup
Removed IDependencyResolverTrackerPolicy. The interface alone with its policy was invoked during registration and contributed to slowing down performance. Since it is not being used internally within Unity itself it was removed to speed up registration process.
5.2.0.304
Speed improvements
This release includes minor speed optimization. Functionality of HierarchicalLifetimeStrategy
and LifetimeStrategy
were merged into one step to eliminate one iteration in strategy chain and improve speed of objects creation. All logic is implemented in LifetimeStrategy
class.
New Features:
New InjectionConstructor(params Type[] types)
Injection constructor could be specified by providing either arguments or types of arguments of the constructor:
Select default constructor:
container.RegisterType<SomeType>(new InjectionConstructor());
Select constructor with SomeType(int, string, float) signature and provide values:
container.RegisterType<SomeType>(new InjectionConstructor(0, string.Empty, 0.0f));
Select constructor with SomeType(string, string, string) signature and provide values for last two:
container.RegisterType<SomeType>(
new InjectionConstructor(
new ResolvedParameter(typeof(string)), string.Empty, string.Empty)));
Select constructor with SomeType(string, string, IUnityContainer) signature and provide values for last two:
container.RegisterType<SomeType>(
new InjectionConstructor(new Type[] { typeof(string), typeof(string), typeof(IUnityContainer) })));
Note: This change could be breaking and affect selection of a constructor with all parameters of type Type: Constructor(Type type1, Type type2)
Changes to HierarchicalLifetimeManager
Class HierarchicalLifetimeManager
now implements IHierarchicalLifetimePolicy
interface.
This interface adds method CrateScope()
and allows registration of hierarchical lifetime managers with child containers.
RegisterSingleton<>()
Added lineup of extension methods for registering Singletons
5.1.0.296
Entire Unity Library as single package. This release includes:
- Unity.Abstractions.2.1.0
- Unity.Container.5.1.0
- Unity.Interception.5.0.3
- Unity.Configuration.5.0.2
- Unity.Interception.Configuration.5.0.3
- Unity.ServiceLocation.2.0.2
- CommonServiceLocator.2.0.1
5.0.1
5.0.0
Release 5.0.0
After few years of inactivity we are finally updating Unity library. The main goal of this release was to preserve compatibility with previous distribution v4.0.1 as much as possible. Unfortunately loss of original signing key prevented creation of compatible assemblies. To eliminate conflicts assembly names and namespaces were changed.
The Unity Container has been split into following assemblies:
- Unity.Abstractions.2.0.0
- Unity.Container.5.0.0
- Unity.ServiceLocation.2.0.0
- CommonServiceLocator.2.0.1
Each of these is available as individual package but Abstractions and Container also distributed as library via Unity.5.0.0
package.
All 1220 tests from previous release are still passing.
New features
- Unity container no longer references CommonServiceLocator
- Added support for .NET 4.0, 4.5, 4.7, .NET Core 1.0+ and .NET Standard 1.0+ where available.
- Container internally uses ConcurrentDictionary to improve multi threading
- Added
DelegateInjectionFactory
which allows free form delegate to serve as Injection Factory - Added support for IEnumerable resolution
- Registration speed increased almost order of magnitude See data
Breaking changes
- Unity has been split into Unity.Abstractions and Unity.Container
- Moved
ServiceLocation
functionality into separate package Unity.ServiceLocation - Interface IBuilderContext now has reference to
IUnityContainer
. This change was required to speed up dependency resoluton. - TearDown has been removed from IUnityContainer
- ResolveAll has been converted to Extension method
Acknowledgements
- Thank you everyone who offered support and help with this release
- Special Thanks to JetBrains team for contributing ReSharper Ultimate license for this project