📜 ⬆️ ⬇️

First look at Unity 2.0

image
Unity is an open source project from the Patterns & Practices group at Microsoft. The goal of the project is to provide a classic IoC framework for developers, which allows instantiating objects in an advanced way and be able to have a flexible configuration. Unity is a separate framework, but is often included in projects as part of the Enterprise Library . With the advent of .NET 4 and Visual Studio 2010, new versions of the Unity and Enterprise Library are on the way. This article covers the beta version of Unity 2.0. To try the framework yourself, visit http://unity.codeplex.com . The release of Unity 2.0 and Enterprise Library 5.0 is scheduled for the same time as the releases of Visual Studio 2010 and .NET 4, that is, this spring.

Some facts about Unity 2.0


When a new product release comes out, the first question that arises is: can I easily update my old binary components with new ones and be happy? The second frequent question: can I use the old version of the product with the new version? For Unity 2.0, the answer to both questions is: YES. You can easily migrate existing applications to the new version of the tool and you can also use versions 1.2 and 2.0 together in the context of a single application. However, in the case of sharing, you need to do several actions to make sure, for example, that the Unity assemblies are located in different folders (since they have the same name) and each of your assemblies depends only on one of the Unity versions.

Speaking of builds, it should be noted that all the functionality of Unity 2.0 is represented by three builds:The first one contains the core of the library, the other two are focused on specific aspects, such as support for offline configuration via XML and the implementation of the Interception pattern. The main difference with the previous version of Unity is the absence of the ObjectBuilder2 assembly, the code of which is now included in the Microsoft.Practices.Unity kernel.

Depending on the purpose for which you used Unity 1.2 and what features you implemented, you may or may not face difficulties migrating your existing code to the new version. At first glance, according to my feelings, in most cases migration is smooth and without problems, but some changes are still present and some old code may be outdated in the light of the new version of Unity.
')

Determination of dependencies with Unity 2.0


Since the main goal of Unity is to resolve dependencies between classes, the primary task is how to express these dependencies. There are two ways: using an offline configuration file and expressing dependencies through a flexible API at runtime.

By default, Unity reads configuration parameters from an XML file, most often these are application configuration files like app.config or web.config . But you are not limited in your choices and you can load configuration parameters from any XML file that was included in your project. For example, you have a my.config file with Unity configuration settings. The following code shows how you can load information from it into the current container instance:

image

This code is slightly different from what you could use in version 1.2. The old code is now marked obsolete. The main difference is the line of code that loads configuration information into the container. You now have a new Configure method for the section object.

Keep in mind that if you use a non-default configuration file, then you need to make sure that the .config file is located in the same folder as the executable file. Below is the code that loads the configuration from the default file:

image

The final code is definitely cleaner than the code written in previous versions. In addition, there is even more pleasant news for Unity developers: Unity 2.0 comes with a very nice configuration tool with which you can “express and declare” your dependencies.


Fig. 1. Section Unity, customizable using the Enterprise Library configuration utility

This tool can save settings to any file, and also can combine sections from the Enterprise Library and Unity together. The tool also opens files that you could create in Visual Studio or somewhere else.

Offline configuration is great, but it is a declarative API. There are many situations where you need more flexibility and, of course, situations in which you choose approaches that offer greater flexibility. An alternative to offline configuration at design time is configuration during execution.

image

The UnityContainer class supports flexible syntax, which allows you to chain into combinations of class methods to achieve the desired configuration. For example, you can use RegisterType to register a type mapping and RegisterInstance to register an instance of a particular type. You can also combine the call with AddExtension to use the Unity interception API. In addition, the UnityContainer class contains a new extension method , IsRegistered , which allows you to check the specified type to see if it has already been registered using the framework.

image

This method is one of the features added in Unity 2.0 and useful in scripts when you intend to integrate configurations together during design and execution. You can use this method to avoid multiple identical registrations that will be automatically resolved using the last rule added. In Unity 2.0 you will also find for yourself a new Collection Registrations , designed to programmatically check for registrations at the time of execution. Registrations returns a collection of ContainerRegistration objects, which are described below:

image

As you can see, the ContainerRegistration object is an exact description of the registration, regardless of how it was created: via XML or programmatically.

Resolving Dependencies with Unity 2.0


Unity 2.0 still contains the Resolve method with the same syntax that you are familiar with from previous versions. After the container has been configured in any way, all we need to do is build instances of the projected types. For this purpose, the Resolve and Resolve <T> methods are used:
image

The resolution method does all the magic to determine the structure of the target type and search for its dependencies, to resolve them. Like many other IoC frameworks, Unity supports the dependencies specified through the designer and injection attributes that can be specified for properties or methods. The instance that returns a Resolve or Resolve <T> contains all the existing dependencies allowed, in the case when the dependency was not resolved, the framework throws an exception.

Unity can also allow generic types, both linked and unbound. Below is the registration of unbound generic type (in which, type T is unknown):

image

The ISpecialLogger <T> type is projected onto a closed type that knows only how to handle integer values. Below, for example, a description of this type:

image

In your code, you ask Unity to allow ISpecialLogger <int> and get an object that knows how to log integer values:

image

Ring links are a serious danger when using Unity and in general IoC containers. Ring dependencies are difficult to identify and should be viewed as a sign of poor application design, and not as a random result due to the lack of functionality in your IoC. When a class provides multiple constructors, Unity defaults to the one with the most parameters. At times, this can lead to ring links, which would never appear when you create classes manually. For example, we have two classes:

image

Everything is fine as long as you instantiate class instances yourself:

image

If you assign Unity to allow a class, you will get a stack overflow:

image

The reason for the exception with stack overflow is that Unity, using the constructor with the largest number of parameters, gets into ring references when it tries to get an instance of MyService to resolve MyContainer , which in turn is required to allow MyService .

In conclusion, it is worth describing that Unity 2.0 contains several new life cycle managers (lifetime managers). In the previous version, we had three predefined managers, plus the ability to create our own. Table 1 describes the managers available in Unity 2.0.

Table 1. Lifecycle Managers in Unity 2.0
Manager
Description
ContainerControlledLifetimeManager
Implements singleton behavior for objects. The object is destroyed (disposed) when the container is destroyed.
ExternallyControlledLifetimeManager
Implements singleton behavior, but the container does not store an object reference, so the object is destroyed after leaving the scope.
Hierarchicalifetimemanager
New in Unity 2.0, implements singleton behavior for objects. But, descendant containers do not share instances with parents.
PerResolveLifetimeManager
New in 2.0, implements a behavior similar to a transient lifetime manager, except that instances are reused in building an object graph (instances are reused across the build graph of the object graph).
PerThreadLifetimeManager
Implements singleton behavior for objects, but limits them to the current thread.
TransientLifetimeManager
Returns a new instance of the requested type for each call. This is the default behavior.
As expected, the default resolution in Unity returns a new instance for each call. The same thing happened in previous versions.

Conclusion


At the time of this writing, the Unity 2.0 framework remained in beta status. This version is nothing revolutionary. However, the configuration has been fixed - an area in which the framework was inferior to other blocks from the Enterprise Library in both forms: with the design and the API. And another important change: now, if you want to use only a clean implementation of the code, you need only one DLL.

The final release is expected in April, immediately after the release of Visual Studio 2010 and the .NET Framework 4. However, Unity 2.0 is not specific to .NET 4 and can also be used for .NET 3.5.

Progg it

Source: https://habr.com/ru/post/84592/


All Articles