Visual Studio не копирует файлы содержимого из проекта с косвенной ссылкой
У меня есть следующая структура проекта:
Library1 <--[project reference]-- Library2 <--[ref]-- Executable
-------- -------- ----------
ContentFile .cs files .cs files
.cs files
Все ссылки на проекты имеют CopyLocal = true.
Когда я строю проект, ContentFile
копируется в Library2
выходной каталог, но не Executable
выходной каталог, означающий, что исполняемый файл отсутствует ContentFile
когда приложение запускается.
Почему файл содержимого копируется в Library2
выходной каталог, но не Executable
"S? Есть ли способ также скопировать его в последний (я хотел бы сделать это без событий сборки, потому что я уверен, что люди забудут об этом)?
Я ищу разумное и поддерживаемое решение; тот, который требует минимальных усилий при добавлении новых проектов или новых файлов содержимого с косвенными ссылками, так что маловероятно просто забыть сделать это.
Использование событий после сборки (например, xcopy ../Library/bin/Debug/SomeDll.dll bin/Debug
); и вручную установить выходной каталог проектов в $(SolutionDir)/bin/...
вместо значения по умолчанию (для каждого проекта) оба быстро превратились в огромный беспорядок. Добавление файлов содержимого в качестве ссылок в "основной проект" также было слишком утомительным. Было бы хорошо, если бы C# имел ту же настройку по умолчанию для выходного файла, что и Visual C++ (то есть $SolutionDir/$Platform/$Configuration
), но это не так.
Я также решил не использовать стандартную процедуру MSBuild вообще и написать собственную цель сборки (например, использование gcc в Atmel Studio), но я совсем не продвинулся. Кроме того, я хочу, чтобы стандартные команды Visual Studio "Build" и "Debug" работали так, как обычно.
ОБНОВИТЬ:
Вот более подробно о том, что я делаю.
У меня есть решение с Executable
проект. Кроме того, есть несколько проектов, которые вы можете назвать Plugin
s. Executable
ссылается на все эти Plugin
с помощью ссылки на управляемый проект.
Поскольку проекты плагинов адаптированы к исполняемому файлу, но могут иметь компоненты многократного использования, основная функциональность часто реализуется в виде External
проект, оставляя Plugin
проект простой обертки (не всегда, хотя).
Сказал External
проекты иногда используют собственные библиотеки DLL, предоставленные третьими сторонами. Эти библиотеки затем добавляются в External
проект как файл содержимого и Copy to output dir
установлен в Copy always
, Таким образом, структура выглядит как на схеме выше:
External <---------------[is not aware of]--------------------+
-------- |
.cs files <--[reference]-- PluginWrapper <--[reference]-- Executable
"Native DLL" ------------- ----------
.cs files .cs files
Странно то, что "Native DLL" копируется в External
выходной каталог (очевидно), а также PluginWrapper
х, но не Executable
"S.
Рабочий процесс разработчика должен был бы написать External
которая работает как полностью изолированная сущность (они используются очень часто), оберните ее PluginWrapper
, а затем только добавить ссылку на проект в PluginWrapper
в Executable
, Я нахожу странным, что это, по-видимому, такая необычная вещь.
Я думал, что, возможно, редактирование Executable
Целевой XML MSBuild (также включающий файлы содержимого с косвенной ссылкой) мог бы решить проблему.
Я мог бы хотеть рассмотреть добавление библиотек DLL к проектам в качестве встроенных ресурсов, как это было предложено, но внедрение таких встроенных библиотек DLL мне кажется странным. В конце концов, измените рабочий процесс разработчика, убрав "[не знает]" из приведенной выше диаграммы и добавив ссылку на проект в External
как предположила Бренда Белл, может быть самым разумным решением, даже если не идеальным.
Обновление 2
Обратите внимание, что идея встроенного ресурса может работать не во всех случаях. Если необходимо поместить зависимость в каталог исполняемого файла (не cwd или что-либо еще), это может не сработать из-за отсутствия прав администратора в папке установки (для распаковки файла из встроенного ресурса). Звучит странно, но это была серьезная проблема с одной из сторонних библиотек, которые мы использовали.
4 ответа
РЕДАКТИРОВАТЬ:
Вы можете поместить весь контент в отдельный проект, установить для всех его записей "контент" и "всегда копировать" и ссылаться на этот проект из внешнего и исполняемого файлов.
-
ИМО вы ищете встроенный ресурс, а не файлы содержимого.
Когда вы компилируете библиотеку 1, файлы содержимого помещаются в ее папку bin. Когда библиотека 2 компилируется, компилятор распознает ссылочный код и включает его (Library 1.dll), но файлы содержимого не распознаются, поскольку они нигде не упоминаются в библиотеке 2. То же самое происходит при связывании библиотеки 2 с исполняемым файлом.
Если ваши файлы содержимого являются относительно небольшими (значки, шаблоны и т. Д.), И вам не нужно редактировать их, если вы потеряете исходный код, тогда вы можете встроить их в качестве ресурсов и предоставить открытый метод для возврата содержимого, такой как:
public static Stream GetResourceContent(string rName){
string resName = System.Reflection.Assembly
.GetExecutingAssembly().GetManifestResourceNames()
.FirstOrDefault(rn => rn.EndsWith("."+rName));
if(resName!=null)
return System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream(resName);
else
return null;
}
Если ваш контент обязательно изменится, например, шаблоны и т. Д., Подумайте о включении копии в исполняемый проект.
Другой вариант - встроить ContentFile как ресурс в сборку Library1 и извлечь ее с помощью Assembly.GetManifestResource().
Смотрите эти ссылки для получения дополнительной информации:
http://www.attilan.com/2006/08/accessing-embedded-resources-using.html
Одним из вариантов ответа Бренды будет добавление файла (ов) библиотеки1 в качестве ссылки (ссылок) в исполняемом проекте. У вас все еще есть записи в проекте, но вам не нужно управлять несколькими копиями каждого файла.
Возможно, вы ссылаетесь на Library1 только из файла XAML, в этом случае Visual Studio не распознает использование. Также добавьте ссылку в код, например, применив атрибут name