редактирует...
Обратите внимание: я изменяю свои фальшивые ссылки на папки, чтобы они более точно отображали, что это не папки, а пространства имен. Некоторые из комментариев здесь были до этого изменения
Я совсем новичок в C#, поэтому простите меня, если я скажу что-то не так.
Я работаю в большом решении, в котором много проектов.
Меня попросили переместить определенный класс, определенный в пространстве имен, из одного из этих проектов в другой. Однако проблема, когда я делаю это, заключается в том, что есть одно определение объекта, на которое больше не ссылаются должным образом. Вот пример:
Первоначальная структура:
Этот файл:
Main\Second.Level.Data\Second.Level.Data.csproj:
Первоначально в нем была эта строка кода:
<Compile Include = "Some\Nested\File\Way\Down.cs" />
Кроме того, здесь упоминался фактический файл:
Main\Second.Level.Data\Some\Nested\File\Way\Down.cs
Новая структура:
Сначала мы удалили строку Compile из 'Main\Second.Level.Data\Second.Level.Data.csproj и добавили аналогичную строку кода в новое пространство имен, которая выглядела так:
File: Main\Main.DataAccess\Main.DataAccess.csproj
Добавлена новая строка кода:
<Compile Include = "New\Location\of\Down.cs" />
И мы переместили фактический файл в новое место, которое сейчас:
Main\Main.DataAccess\New\Location\of\Down.cs
Когда это сделано, кажется, что все ссылки (т. е. все операторы использования) работают, кроме одной. Есть один оператор using, который выглядит так:
using Main.Second.Level.Data.Yet.Another.Nested.File.Objects
В старом пространстве имен этот оператор using работал нормально, а в новом — нет. В частности, он терпит неудачу на третьем элементе (уровень). Моя IDE выдает ошибку «Не удается разрешить символ «Уровень»».
Я очень подозреваю, что причина этого заключается в том, что на самом деле существует другое пространство имен, которое называется просто «Main.Second», внутри которого есть собственный файл Main.Second.csproj. Я ни для чего не использую эту папку или файлы в ней, однако я не могу понять, как система может узнать разницу между:
using Main.Second.Level.Data.Yet.Another.Nested.File.Objects
и
using Main.Second.Some.Other.Unrelated.Stuff
Другими словами, я не понимаю, как точечная запись может указать, где начинается или заканчивается имя пространства имен.
Приложение №1:
Я определил, что проблема в том, что в файле csproj целевого проекта нет ссылки на новый проект (или, по крайней мере, я совершенно уверен, что это так). Чтобы решить эту проблему, я попытался вручную добавить эту ссылку. Обратите внимание: я использую JetBrains Rider IDE и пробовал несколько автоматических методов добавления ссылки, но ни один из них не сработал.
Чтобы добавить ссылку, я нашел блок ItemGroup со всеми другими ссылками на проект и добавил новый блок. Это выглядит так:
<ItemGroup>
<ProjectReference Include "..\Other.Project\Other.Project.csproj">
<Project>{fh9w8es3-nota-real-guid-example1}</Project>
<Name>Other.Project</Name>
</ProjectReference>
<ProjectReference Include "..\Main.Second.Level\Other.Project.csproj">
<Project>{AD8234HS-NOTA-REAL-GUID-EXAMPLE2}</Project>
<Name>Main.Second.Level</Name>
</ProjectReference>
</ItemGroup>
Обратите внимание, что при этом мне пришлось придумать руководство для элемента Project. Я пришел к выводу (после исследования), что этот GUID будет тем, который в настоящее время существует в файле решения в корне решения, в частности, это второй GUID, показанный для этого проекта. Мой приведенный выше пример — это именно то, как я сделал свой код (в частности, в том, что GUID, скопированный из файла решения, — это все заглавные буквы, а те, что в файле csproj, — нет.
Однако это не решает мою проблему. Однако я чувствую, что очень близок к решению.
Да, мне сказали это, но это не работает. Пространство имен объекта, на который делается ссылка, не изменилось, но оно недоступно из нового местоположения. Возможно, нельзя ссылаться на объект из одного проекта в другом?
Очень сложно сказать, в чем проблема. Можете ли вы каким-то образом предоставить минимальный воспроизводимый пример?
Ведь без какого-либо способа воспроизвести проблему мы просто не сможем помочь. Вы можете абсолютно точно ссылаться на тип из одного проекта в другом проекте, если он является общедоступным и существует ссылка (прямая или косвенная) из проекта-потребителя на проект-поставщик. Но опять же, без репродукции что-то конкретное сказать сложно.
Спасибо всем, мне, вероятно, потребуется несколько дней, чтобы создать что-то подобное (и, к сожалению, я не могу опубликовать фактический код). Я обнаружил одну вещь в файле .csproj нового проекта под названием «ProjectReference», которая, кажется, указывает точный способ ссылки на внешний проект, мне нужно исследовать это дальше, я думаю.
Правильный ответ на исходный вопрос, который я поставил, заключается в том, что вам нужно добавить ProjectReference в ItemGroup, как указано в добавлении, которое я разместил по исходному вопросу.
Однако в моем конкретном случае это было невозможно, потому что это вызывало циклическую ссылку. Пример:
Проект A: имел ссылку на проект B Проект A: определил и широко использовал внутренний класс, а также использовал классы в проекте B.
Проект B: были классы, которые использовались только в проекте B.
Мое изменение попыталось добавить один из классов из проекта A в проект B, однако для этого потребовалось бы добавить обратную ссылку на проект A, что и вызвало циклическую ссылку.
Чтобы решить эту проблему, я сделал следующее:
Определил интерфейс в проекте B, который будет работать для моего нового класса, определенного в проекте A.
Сделайте класс Project A расширением этого интерфейса
Измените ссылки на класс проекта A, которые были в проекте B, чтобы ссылаться на интерфейс вместо определенного класса. Это устранило необходимость в обратной ссылке.
Извините, это так расплывчато, но это проприетарный код (а также чрезвычайно сложный), поэтому его нецелесообразно публиковать здесь, но я думаю, что изложил суть решения.
using
директивы и файловая структура только условно связаны друг с другом. Вам нужно посмотреть объявление пространства имен в классе, к которому вы хотите получить доступ. Это определяет, какаяusing
директива вам нужна.