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.
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:
Attribute | Meaning |
---|---|
[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.
The attribute has the following optional parameters:
Parameter | Default | Meaning | ||||||
---|---|---|---|---|---|---|---|---|
Name | null |
ID of the object to be found (don't ask why it is called "name" here). | ||||||
SearchMode | Up |
Search only in local work item's locator (Local ),
or in parent work items' locators as well (Up ) | ||||||
NotPresentBehavior | CreateNew |
What to do if dependency is not found. Options are:
| ||||||
CreateType | Type of the parameter | Type 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.
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.
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:
Parameter | Default | Meaning |
---|---|---|
Type | The 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. |
Required | true |
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>(); } |
This attribute is used to specify dependencies on objects that are not services, and thus have specific IDs. It has the following parameters:
Parameter | Default | Meaning |
---|---|---|
ID | none (required) | ID of the object to be found. Cannot be null |
CreateIfNotFound | false |
If true, and the object is not found, will attempt to create a new object. |
Required | true |
If true, and the object is not found or created, will throw DependencyMissingException .
If false, will return null for missing object. |
Type | The 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]
.
Programming Tools & Info | Copyright (c) Ivan Krivyakov. Last updated: April 6, 2008 |