Здесь на самом деле есть два сценария - использование строгих имен / GAC или не использование строгих имен.
Если вы используете строгие имена и устанавливаете компоненты в GAC, тогда .Net захочет использовать версию компонента, на которую ссылался клиент, когда он был скомпилирован. Таким образом, в вашем примере было бы вполне возможно, чтобы Project ссылался на базу данных V2, в то время как Logging ссылался на базу данных V1, потому что DLL могут храниться параллельно в GAC. Так что, если вы действительно хотите, чтобы Ведение журнала использовало V2 вместо V1, вам нужно изменить файлы конфигурации, чтобы сказать, что «ссылка на V1 должна указывать на V2». Есть разные места для этого - файл приложения, машинный файл и т. Д.
Если вы не используете строгие имена, то .Net по умолчанию будет использовать версию DLL, которая находится в той же папке, что и клиент. Предположим, вы развернули Project, CommonControls и Logging в той же папке, что и база данных V2. Тогда, даже если ведение журнала было построено для базы данных V1, оно попытается использовать компонент в той же папке, то есть в базе данных V2. Пока V2 может предоставлять те же общедоступные классы и методы, которые Logging хочет использовать, он будет работать нормально.
В моей среде, где все наши приложения являются внутренними, мы не используем GAC. Мы просто разворачиваем все файлы, которые нужны приложению, в одну папку. Если у вас много общих компонентов, то синхронизировать файлы конфигурации будет просто кошмаром.
Это все сильно отличается от COM, где все приложения подобрали текущую зарегистрированную копию DLL (при условии, что V1 и V2 были двоично-совместимыми).