Разные экземпляры одной сборки
От: VladD2 Российская Империя www.nemerle.org
Дата: 20.01.18 15:37
Оценка:
Всем привет!

Вопрос больше для наших экспертов, так что в первую очередь хочется услышать ответы Nikov-а, Sinix-а и т.п.

Введение

Если в Розлиновском компиляторе/движке IDE создать два разных проекта (в одном солюшене) и дать в них ссылки на две одноименных и одноверсионных сборок но содержащих разные типы или сигнатуры (т.е. отличающихся по содержимому), то он спокойно с этим работает. В одном проекте видна одна сигнатура. В другом, другая. Правда при сборке и запуске получается исключение о несовпадении сигнатур, так при компиляции в output-каталог кладется одна из этих сборок (видимо они затирают друг друга), а дотнет спокойно резолвит вторую сорку в первую, так как у них совпадает идентити. Но если по колдовать, то таки можно добиться корректной работы такой программы.

В дотнете сложно загрузить сборку с одинаковой идетнити (с одинаковыми: именем + версией + и без пабик токена) в один и тот же AppDomain. Однако с помощью события AppDomain.CurrentDomain.AssemblyResolve, метода Assembly.LoadFile и какой-то матери мне удалось загрузить два ОДИНАКОВЫХ типа из двух одноименных и одноверсионных сборок (положенных в два подкаталога). При этом сами типы отличались. У них были одноименные функции с разными сигнатурами.

Предисловие

При построении деревьев пространств имен и типов (в компиляторе или движке IDE) можно идти двумя путями:

1. Загрузить отдельно каждую сборку построив дерево пространств имен только для этой сборки и потом построить по ним общее дерево типов для каждого проекта. При этом можно загружать сборки вне контекста конкретного проекта. Если два проекта ссылаются на одну сборку, то они будут разделять символы (типы, пространства имен и т.п.) из одинаковых сборок.

2. Загружать сборки в деревья пространств имен и типов каждого проекта в отдельности. При этом получится создать иерархии в которых одна и та же сборка ссылается на типы из одинаковых по имени и версии, но разных по содержанию сборок.

Преимущество пути 1 заключается в том, что символы не дублируются для каждого проекта. А это значит что будет экономиться память и процедура проектного поиска поиска символов упрощается. Каждый проект будет просто ссылаться на один и тот же символа.

Так же первый путь позволяет легко реализовать такие фишки как глобальные алиасы C# (пример: global::SomeNamespace.SomeType).

Но при выборе пути 1 не удастся иметь разные по содержимому, но одинаковые по идедентити (имени + версии + пабик токену) сборки в составе разных проектов. Ведь внутри типов есть ссылки на типы из референс-сборок. Если грузим сборку только один раз, то физически не может создать иерархию для двух разных по содержанию референсных сборок.

В общем-то такое может получиться только по глупости разработчиков не поменявших версии у разных по содержанию сборок. Но физически то это возможно.

Второй путь неприятен тем, что у нас получаются несвязанные наборы символов для каждого проекта. А это не только потери памяти, но и трудности в поиске символов в рамках всего солюшена.

Вопрос 1

Собственно вопрос в том насколько разумно выбирать первый подход (с однократной загрузкой символов для сборок в рамках всего солюшена)?

Как бы очень хочется. Но колется.

Вопрос 2

Может быть можно сделать некий промежуточный вариант в котором при наличии одинаковой иерархии референсных сборок можно будет иметь одинаковую иерархию и создавать параллельные иерархии в ином случае.

ЗЫ

Не уверен, что объяснил все понятно. Если что задавайте уточняющие вопросы.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.