Programming Microsoft ASP.NET 4 - Dino Esposito [301]
When you use the plain attribute, the contract name defaults to the name of the member. In this case, it is typeof(IPasswordFactory). What about exports?
Consider the following example:
[Export(typeof(IPasswordFactory))]
public class DefaultPasswordFactory : IPasswordFactory
{
public String Create(Int32 passwordLength)
{
// Create the password
}
protected virtual String GeneratePasswordCore(Int32 passwordLength)
{
// ...
}
}
Deployed to an assembly located in the specified plugin folder, the class DefaultPasswordFactory exports the typeof(IPasswordFactory) factory. If the class features the simple Export attribute, the contract then corresponds to the class name, thus missing the previous import.
Note that if an export, in turn, misses one key import, the export is ignored to ensure the stability of the solution. If multiple exports qualify to resolve the same import, you get a composition exception.
Unity at a Glance
Unity is an open-source project from the Patterns & Practices group at Microsoft, which is attempting to provide an IoC framework for developers to build object instances in a smart and highly configurable way. Unity works as a standalone framework, but it’s also packaged along with Enterprise Library. To add Unity to a project, you add a reference to the Microsoft.Practices.Unity assembly. You optionally add a reference to Microsoft.Practices.Unity.Configuration if you configure the library using the application’s configuration file.
Let’s see how to accomplish some key IoC operations with Unity, such as registering types both programmatically and declaratively.
Registering Types and Instances
Just like any other IoC library, Unity is centered around a container object. In Unity, the container type is UnityContainer, and you use it to register types and instances, as shown here:
var container = new UnityContainer();
container
.RegisterType .RegisterType var serviceLayer = container.Resolve You use the RegisterType method to establish a mapping between an abstract type and a concrete type. If the same abstract type should be mapped to different types in different contexts of the same application, you can use the following overload: container .RegisterType .RegisterType The additional string parameter disambiguates the request and gives Unity enough information about which concrete type to pick up. You use RegisterInstance instead of RegisterType to supply the container a prebuilt instance of a type. In this case, Unity will use the provided instance instead of creating one on its own. Does it really make sense for an application to pass to a factory the instance it will get back later? The purpose is to preserve the benefits of an IoC also in situations in which you can’t annotate a class to be automatically resolved by Unity. To see an example of this, let’s first introduce the syntax required to annotate constructors and properties for injection. When requested to create an instance of a given type, Unity gets information about the constructors of the type. If multiple constructors are found, Unity picks up the one with the longest signature. If multiple options are available, an exception is thrown. It might be the case, however, that you want a particular constructor to be used. This requires that an attribute be attached to the selected constructor: [InjectionConstructor] public MyClass() { ... } If you have no access to the source code, you might want to consider RegisterInstance. Similarly, if injection happens through the setter of a property, you need to decorate the property accordingly, as shown here: private ILogger _logger; [Dependency] public ILogger Logger { get { return _logger; } set { _logger = value; } }