Ответ 1
Добавьте ссылку Library1 в исполняемый проект.
У меня есть следующая структура проекта:
Library1 <--[project reference]-- Library2 <--[ref]-- Executable
-------- -------- ----------
ContentFile .cs files .cs files
.cs files
Все ссылки на проект имеют CopyLocal = true.
Когда я создаю проект, ContentFile
копируется в каталог вывода Library2
, но не в каталог Executable
output, что означает, что при запуске приложения отсутствует ContentFile
.
Почему файл содержимого копируется в каталог Library2
output, но не Executable
? Есть ли способ скопировать его в последнюю (я бы хотел сделать это без событий сборки, потому что я уверен, что люди это забудут)?
Я ищу разумное и поддерживаемое решение; тот, который требует минимальных усилий при добавлении новых проектов или новых косвенно связанных файлов содержимого, так что как можно мало просто забыть об этом.
Использование событий Post-Build (например, xcopy ../Library/bin/Debug/SomeDll.dll bin/Debug
); и вручную устанавливая выходной каталог проектов на $(SolutionDir)/bin/...
вместо стандартного (для каждого проекта), оба быстро становятся огромным беспорядком. Добавление файлов содержимого в виде ссылок в "основной проект" было слишком утомительным. Было бы замечательно, если бы С# имел тот же самый параметр по умолчанию для выходного файла, что и Visual С++ (т.е. $SolutionDir/$Platform/$Configuration
), но это не так.
Я также рассматривал возможность использования стандартной процедуры MSBuild вообще и запись пользовательской цели сборки (например, использование gcc в Atmel Studio), но я совсем не ушел. Кроме того, я хочу, чтобы стандартные команды "Build" и "Debug" Visual Studio работали так, как обычно.
Вот более подробно о том, что я делаю.
У меня есть решение с проектом Executable
. Кроме того, существует множество проектов, которые вы могли бы назвать Plugin
s. Executable
ссылается на все те Plugin
через управляемую ссылку на проект.
Поскольку проекты плагина адаптируются к исполняемому файлу, но могут иметь многоразовые компоненты, основная функциональность часто реализуется в проекте External
, оставляя проект Plugin
простой оболочкой (не всегда).
Указанные проекты External
иногда используют собственные DLL файлы, предоставляемые третьими лицами. Затем эти 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
.
Тогда рабочий процесс разработчика должен был бы написать External
, который будет работать как полностью изолированный объект (они часто используются повторно), оберните его с помощью PluginWrapper
, а затем добавьте ссылку на проект в PluginWrapper
до Executable
. Мне показалось странным, что это, по-видимому, такая необычная вещь.
Я подумал, что, возможно, редактирование Executable
целевого XML файла MSBuild (включая косвенно связанные файлы содержимого) могло решить проблему.
Возможно, мне захочется заглянуть в добавление DLL к проектам в виде встроенных ресурсов, как было предложено, но встраивание таких DLL, как это кажется мне странным. В конце концов, сменив рабочий процесс разработчика, разделив "[не знаю]" на приведенной выше диаграмме и добавив ссылку на проект на External
, как предложила Бренда Белл, может быть самым разумным решением, даже если оно не идеально.
Обновление 2
Обратите внимание, что встроенная идея resouce может не работать во всех случаях. Если необходимо установить зависимость в исполняемом каталоге (не cwd или что-то еще), это может не работать из-за отсутствия привилегий администратора в папке установки (чтобы распаковать файл из встроенного ресурса). Звучит странно, но это была серьезная проблема с одной из сторонних библиотек, которые мы использовали.
Добавьте ссылку Library1 в исполняемый проект.
EDIT:
Вы можете поместить весь контент в отдельный проект, установить все его записи в "контент" и "копировать всегда" и ссылаться на этот проект с внешнего и исполняемого
-
IMO вы ищете встроенный ресурс, а не для файлов содержимого.
При компиляции библиотеки 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
Один из вариантов ответа Бренды - добавить файл содержимого Library1 в качестве ссылки в проекте Executable. У вас все еще есть записи в проекте, но вам не нужно управлять несколькими копиями каждого файла.
Возможно, вы ссылаетесь на Library1 только из файла XAML, в этом случае Visual Studio не распознает использование. Добавьте ссылку в коде, например, применяя атрибут name