c# - liste - cran r



Est-ce que "Copy Local" est transitif pour les références de projet? (2)

C'est très simple, n'a rien à voir avec Copy Local. MSBuild recherche dans les métadonnées d'un assembly pour voir quelles sont les dépendances pour un assembly. Alors, vous pouvez, lancez ildasm.exe sur l'assembly et double-cliquez sur le manifeste. Assurez-vous d'essayer ceci pour avoir un aperçu. Vous verrez les directives .assembly . Inséré par le compilateur lors de la construction de l'assemblage, seuls les assemblages référencés que vous avez réellement utilisés dans votre code seront listés.

Si MSBuild peut trouver un tel assembly dans le même répertoire, il le copie automatiquement. Sinon, il passera silencieusement la copie.

De cela, vous pouvez déduire les modes de défaillance. Il ne peut pas copier les DLL non managées, elles n'apparaissent pas dans les métadonnées. Il ne peut pas copier les assemblys dont vous avez une dépendance indirecte via Assembly.Load / From (), ils n'apparaissent pas non plus dans les métadonnées. Il ne peut pas copier les assemblys qui n'ont pas encore été construits, un problème d'ordre de construction. Et il ne peut pas copier les assemblys dont la propriété Copy Local est définie sur False. Ce qui n'est normalement un choix valide que si l'assembly est présent dans le GAC, aucune copie requise.

Pour de tels cas, vous devez aider, XCOPY dans un événement de post-construction fait le travail.

Wrt. le dupe proposé: Puisque ce queston suggère le contraire de la question liée , je préférerais penser que ce n'est pas dupe.

D'abord , j'ai lu Quelle est la meilleure pratique pour "Copier Local" et avec des références de projet? (aussi ceci ) et je vais devoir essayer de toute façon, mais obtenir des commentaires généraux sur ceci semble nécessaire car les docs sur ces trucs sont horribles et je suis seulement sur VS2010 et peut-être ils ont changé quelque chose dans les nouvelles versions qui seront bon à savoir.

Deuxièmement , je ne suis intéressé par les références de projet pour cette question que j'ai lu que les assemblées du GAC sont traitées différemment et le GAC n'est pas pertinent pour mon problème.

Troisièmement , après avoir lu la dupe suggérée, mais plus encore la belle réponse de @Albireo, il semblerait qu'il est important de différencier les dépendances de fichiers , où la dépendance fait référence à un fichier dll et à des dépendances de projet (ie ce que je demande) about), où la dépendance référence un projet et implicitement le fichier de sortie de ce projet.

En tout cas, voici la situation, un peu particulière je pense, mais quand même:

  • 2 projets exécutables en C #
  • n projets d'assemblage C # dll
  • Les 2 exécutables ont des répertoires de sortie différents car ils seront déployés séparément et de cette façon ils sont également séparés sur la machine de développement
  • Les 2 exécutables ont des dépendances sur certains des assemblys de DLL (qui peuvent dépendre l'un de l'autre)
  • Il y a trois répertoires de sortie:
    • /x1 pour le projet exécutable 1
    • /x2 pour le projet exécutable 2
    • /lib pour toutes les assemblées dll

Les assemblys DLL ont tous la valeur Copy Local pour leurs références de projet, car ils sont tous construits dans le même répertoire de sortie.

Les 2 projets exécutables ont défini Copy Local sur true pour toutes les références de projet d'assemblage de DLL qu'ils référencent directement, de sorte que les DLL seront copiées dans /x1 /x2 respectivement.

La question est maintenant traitée. aux DLL qui ne sont pas directement référencées par un projet exécutable, mais uniquement transitoirement via un assembly référencé: Les assemblys, qui sont uniquement référencés transitoirement par un autre assembly, sont copiés dans le dossier de sortie de l'exécutable, lorsque "Copy Local" est défini sur vrai sur le premier assemblage?

Exemple:

  • x1.csproj (egOutput = x1/one.exe )
    • Référence: dlA.csproj (par exemple, Output = lib/a.dll ) avec Copy Local = *true*
    • (pas de référence directe sur b.dll)
  • dlA.csproj (par exemple Output = lib/a.dll )
    • Référence: dlB.csproj (par exemple, Output = lib/b.dll ) avec Copy Local = **false**
    • (pas de référence directe sur c.dll)
  • dlC.csproj (par exemple Output = lib/c.dll )
    • (pas d'autres références pertinentes)

Ainsi, nous avons une dépendance logique de one.exe -> a.dll -> b.dll -> c.dll , où seulement a.dll avec évidemment être copié dans le répertoire de sortie de one.exe . Est-ce que les deux autres DLL seront également copiées dans le répertoire de sortie? Est-ce documenté quelque part?

Et, oui, je l'ai essayé. Et, oui, ça a l' air de marcher, mais je ne l'ai pas encore assez enfoncé et de toute façon il y a peut-être quelque chose de plus que j'ai peut-être manqué. (Et aussi il y a la question par rapport à n'importe quel document officiel.)


il semblerait aussi qu'il est important de différencier les dépendances de fichiers, où la dépendance fait référence à un fichier d'assemblage dll et aux dépendances de projet (c'est-à-dire de quoi je parle), où la dépendance référence un projet et implicitement le fichier de sortie de ce projet.

Non, pas vraiment.

MSBuild ne se soucie pas vraiment si la référence pointe vers un autre projet dans la solution ou vers une DLL.

Si ProjectA dépend de ProjectB pour construire ProjectA ProjectB doit être déjà construit (et mis à jour), MSBuild va alors tirer sa DLL (pas son code C #) et le lier à ProjectA .

L'ajout d'une référence de projet à la place d'une DLL est "du sucre syntaxique" pour votre commodité: de cette façon, MSBuild sait qu'il doit choisir la sortie du projet référencé, quelle que soit la sortie.

Sinon, vous devrez pré-compiler manuellement la dépendance, trouver sa DLL et la lier au projet, en répétant le processus chaque fois que vous changez de configuration de construction, déplacez ou renommez les choses. Pas vraiment pratique.

Est-ce que les deux autres DLL seront également copiées dans le répertoire de sortie?

Si un type d'élément d'une dépendance est utilisé directement à partir du projet où l'assembly est référencé, cette référence sera copiée.

Un exemple pourrait être cette disposition de la solution:

  • MySolution
    • MySolution.ConsoleApplication
    • MySolution.FirstDependency
    • MySolution.SecondDependency
    • MySolution.ThirdDependency
    • MySolution.FourthDependency

Avec cette chaîne de dépendance:

  • MySolution.ConsoleApplication
    • MySolution.FirstDependency
      • MySolution.SecondDependency
        • MySolution.ThirdDependency
        • MySolution.FourthDependency

Si vous construisez cette solution, vous remarquerez que dans le MySolution.ConsoleApplication sortie MySolution.ConsoleApplication il y aura les DLL pour MySolution.FirstDependency , MySolution.SecondDependency et MySolution.ThirdDependency mais pas de DLL pour MySolution.FourthDependency .

Pourquoi est-ce vrai? Lorsque MSBuild construit MySolution.SecondDependency il remarque qu'il y a une dépendance déclarée à MySolution.FourthDependency , mais comme il ne trouve aucune utilisation de n'importe quel type d'élément de MySolution.FourthDependency dans le code MySolution.SecondDependency , il décide d'effectuer une certaine "optimisation" et omet l'assembly MySolution.FourthDependency partir de la sortie.

Ce même problème m'a mordu dans le passé quand j'ai ajouté NuGet AutoMapper à une «dépendance profonde»: l'ajout d'AutoMapper ajoute deux références d'assemblage, AutoMapper et AutoMapper.Net4 , où le second assemblage est chargé par le premier quand il doit effectuer certain type d'action sur les nouveaux objets de collection introduits par le .NET Framework 4. Puisque le second assemblage est chargé par réflexion, MSBuild pense qu'il est inutilisé et ne prend pas la peine de le copier.

Donc, oui , ils seront copiés aussi longtemps que vous les utilisez directement et non par réflexion.

Est-ce documenté quelque part?

Ce comportement semble être une "fonctionnalité" de MSBuild, j'ai réussi à trouver un billet de blog par des gens de Microsoft lorsque j'ai rencontré ce problème, mais je ne le trouve pas encore pour le moment.





copy-local