Не очень понятен вопрос.
Если про то как DI понимает какую имплементацию использовать - все просто, вы сами ее и указываете для конкретного интерфейса.
А если вам интересно как DI понимает что передать в конструктор: через рефлексию, в Type есть метод GetConstructors() - получить список ConstructorInfo, описывающих каждый из задекларированных конструкторов. Далее можно получить список параметров (ParameterInfo) через GetParameters() и найти тот, все типы параметров которого известны DI, инстанциировать их и затем уже инстациировать запрошеный класс, как например контроллер, используя, например, Activator.CreateInstance куда передается тип нужного нам класса и список аргументов.