-
Notifications
You must be signed in to change notification settings - Fork 7
Conventions Based Binding
The contextual binding system can also be used to implement a conventions-based binding system, if you prefer conventions over declarative configuration. Many people prefer to keep infrastructure dependencies like attributes out of their code — this can serve to keep the codebase clean, at the expense of clarity for newcomers.
For example, let’s say you have two sources for configuration in your application, a LocalConfigurationSource
that loads configuration information from a local file, and a RemoteConfigurationSource
that loads configuration from a remote database. Services that depend on configuration information will need one or the other of these services to set up configuration. Let’s say you have a consuming service that loads some of its configuration from the local source, and some from the remote source:
public class Service {
public Service(IConfigurationSource remoteConfig, IConfigurationSource localSource) {
//...
}
}
In order to get Ninject to resolve these dependencies and call this constructor, you will need to declare bindings that differentiate between the two implementations of IConfigurationService
. If you favor a declarative approach, you could create [Remote]
and [Local]
attributes, and use them to decorate the individual constructor arguments:
public class Service {
public Service([Remote] IConfigurationSource remoteConfig, [Local] IConfigurationSource localSource) {
//...
}
}
Then your bindings would look like this:
Bind<IConfigurationSource>().To<RemoteConfigurationSource>().WhereTargetHas<RemoteAttribute>();
Bind<IConfigurationSource>().To<LocalConfigurationSource>().WhereTargetHas<LocalAttribute>();
However, if you’d rather not have to put the attributes in your constructor, you can rely on a conventions-based approach instead. For example, you can create a rule that says that if you want an instance of RemoteConfigurationSource
, your argument has to begin with “remote”, and if you want an instance of LocalConfigurationSource
, it has to begin with “local”. To do this, you would create bindings like this:
Bind<IConfigurationSource>().To<RemoteConfigurationSource>().Only(When.Context.Target.Name.BeginsWith("remote"));
Bind<IConfigurationSource>().To<LocalConfigurationSource>().Only(When.Context.Target.Name.BeginsWith("local"));
By using these bindings, your consuming service could have a constructor with no attributes, as shown in the first code example on this page.