The process that examines the model, looks for attributes, and uses the injector to inject in reference data is controlled by the IModelInjectorFactory interface.  The default implementation, DefaultModelInjectorFactory, controls the injection process.  I’m going to explain a little about what this factory does.  Suppose we had this class:

public class X
{
    [ModelInjection(LookupType = typeof(KeysInjector))]
    public List<string> Keys { get; set; }

    [ModelInjection]
    public List<string> Items{ get; set; }

    [ModelInjection(Key = “A”)]
    public List<string> Values{ get; set; }

All three do something a little different.  The default injector factory examines this class, looking for the ModelInjectionAttribute definition, and finds:

Keys [KeysInjector Lookup]

Items [List<string>]

Values[List<string>, A key]

How it processes each works a little differently.  In the first scenario, since the LookupType has to point to a type to implement IModelInjector, the full control is given by the binder to use the lookup type and not look elsewhere.  The KeysInjector class is instantiated, its Inject method called, and the results are passed to the setter.  In the second scenario, a current injector, ModelInjectors.Current , must be not null.  The current model injector could be an instance of a class of your own design, or one of the in-built DI-based injectors (Unity, Castle currently supported).

What this means is in Global.Asax or somewhere, you have to set the Current property of the ModelInjectors static class with the model injector of your choice.  When the LookupType is not specified, the default is this property value, and if not null, the Items property would be bound with the value mapped to the List<string> type in the DI container, whereas the Values property would be bound with the List<string> type that’s also mapped to the A key (as most DI containers support multiple registrations of a single type separated by key).

All of this process is built in, but you could very well override the default factory and add your own specific implementation, or replace it altogether by supplying a new model injector factory to the ModelInjectors.CurrentFactory static property.  This gives you full control over the model binding process.