Programming Tools & Info

CAB Dependency Attribute Types

This document is a part of the "Inside CAB Dependency Injection" article. It is relatively self-contained, but you still may find it useful to read the whole article from the beginning.

Standard Dependency Attributes

Dependencies of CAB objects are specified using custom attributes in code. For each injection constructor parameter, injection method parameter, or injection property, CAB user may apply one of the following attributes:

[Dependency] Locate an object by type and/or ID, with ability to create a new object if the dependency is not found.
[CreateNew] Always create a new object for this dependency.
[ServiceDependency] Locate a service by type. Supports advanced features such as service type being different from the parameter type, and add on demand.
[ComponentDependency] Locate an object by type and non-null ID. A proper subset of features offered by [Dependency]

At most one dependency attribute can be applied. Parameters without attribute are treated as if they had a [Dependency] attribute with default settings. Properties without attribute do not participate in dependency injection. In addition, user may specify his/her own custom dependency attribute derived from the abstract ParameterAttribute class. This allows to customize dependency injection if necessary.

NOTE: private/protected constructors, methods and properties are silently ignored by CAB and do not participate in dependency injection.

Dependency attributes influence the way CAB object builder locates object dependencies. Each attribute is dicussed in detail below.

[Dependency] Attribute

The attribute has the following optional parameters:

Namenull ID of the object to be found (don't ask why it is called "name" here).
SearchModeUp Search only in local work item's locator (Local), or in parent work items' locators as well (Up)
NotPresentBehaviorCreateNew What to do if dependency is not found. Options are:
CreateNewAttempt to create a new object. This will obviously fail if the type to be created is abstract or an interface.
ReturnNullReturn null. For value types this returns the default value of the type.
ThrowThrow DependencyMissingException
CreateTypeType of the parameterType of object to create if the dependency is not found and NotPresentBehavior is CreateNew. Must be assignable to the parameter type.

[Dependency] is a "universal" dependency attribute defined by the ObjectBuilder assembly. Its behavior boils down to the type to look for (which is always the parameter's exact type), and object ID. Remember that services have object IDs of null, while other objects have specific object IDs.

Objects added to Items and other collections without an explicit ID cannot be resolved as dependencies. This because they will be given a "random" ID at run-time, and you cannot possibly know what it is.

[CreateNew] Attribute

For parameters or properties with this attribute, CAB will not even attempt to locate a dependency. Instead, it will create a new instance of the parameter type every time the object is built up. The type created is always the type of the parameter. If that type is abstract or an interface, initialization will fail with an ArgumentExceptions.

Note, that CreateNew is not a "shortcut" for [Dependency(NotPresendBehavior=NotPresentBehavior.CreateNew)]. The former will create a new object always, while the latter will create a new object only if the dependency is not found.

[ServiceDependency] Attribute

This attribute specifies a dependency on a service, i.e. the object ID is always assumed to be null. It has the following optional parameters:

TypeThe type of the parameter The object type to look for. The object must be registered under exact same type in the locator. It may not be the actual run-time type of the object, but one of its base types or interfaces.
Requiredtrue If true, and the dependency is not found, throw a ServiceMissingException. Otherwise, return null.

Note, that [ServiceDependency] is not a "shortcut" for [Dependency]. While you can locate services using [Dependency], there are certain differences between the two.

First, [ServiceDependency] can look up a type that is different from the parameter's compile type.

Second, it supports the "add on demand" feature. If the service in question has been added via the AddOnDemand() method, [ServiceDependency] will create a new instance. This is different from [Dependency(NotPresentBehavior=NotPresentBehavior.CreateNew)], because the type of the service created may differ from the parameter's type, and even from the Type setting of the [ServiceDependency] attribute:

interface IService {} class BasicService : IService {} class FancyService : BasicService {} class FancyServiceConsumer { [ServiceDependency(Type = typeof(BasicService))] public IService Service { set { _service = value; } } IService _service; } void FancyServiceInjection(WorkItem workItem) { workItem.Services.AddNew<FancyService, BasicService>(); FancyServiceConsumer consumer = workItem.Items.AddNew<FancyServiceConsumer>(); }

[ComponentDependency] Attribute

This attribute is used to specify dependencies on objects that are not services, and thus have specific IDs. It has the following parameters:

IDnone (required) ID of the object to be found. Cannot be null
CreateIfNotFoundfalse If true, and the object is not found, will attempt to create a new object.
Requiredtrue If true, and the object is not found or created, will throw DependencyMissingException. If false, will return null for missing object.
TypeThe type of the parameter Specifies the type to be created if the object is not found and CreateIfNotFound is true. The type specified here is not used for look up in the locator. Objects are always looked up by the parameter type.

Unlike previous attributes, [ComponentDependency] is redundant: it is a shortcut for the [Dependency] attribute with appropriate values, and in fact shares a portion of internal implementation with [Dependency].