【问题标题】:How C# projects link the assembliesC# 项目如何链接程序集
【发布时间】:2018-05-11 07:25:18
【问题描述】:

我想问一个关于 C# 如何链接其依赖关系的问题。

第一种情况: 我有一个链接例如的 C# 项目系统程序集。如果我从 Assembly->Framework 窗口添加引用:

然后双击参考视图上的系统程序集:

程序集的路径是:C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework.NETFramework\v4.5.2\System.dll

但是如果我启用了 .nuget 并且它已经下载了程序集,系统程序集的链接将神奇地更改为:C:\Users\.nuget\packages\Microsoft.NETCore.Portable.Compatibility \1.0.0\ref\netcore50\System.dll

为什么我说“神奇”是因为我看不到明确表示的地方 - 从现在开始从那个方向进行组装。

第二种情况: 当我下载了 .nuget 程序集后,在“项目参考”窗口中我会看到下一件事:

两个不同版本的程序集链接到我的项目,一个来自.nuget所在的地方,另一个来自.NET Framework所在的地方。问题:会考虑哪一个?两者都有?

不过,只是一个想法。

当我使用 C++ 项目时,一切都非常清晰明了,我可能安装了几个不同的 SDK,但是当我定义 SDK 版本和要使用的工具集时 - 项目将从定义的位置获取程序集。它不会尝试从不同的地方加载东西,除非我指定了。

也许 C# 项目具有类似的配置能力,但我不知道它们。 有人可以帮我理解吗?

更新

刚刚意识到我在这里的陈述:当我下载了 .nuget 程序集后,在项目参考窗口中我看到了下一件事: 可能令人困惑。在我列出的不同程序集版本中添加全屏截图:

另外,添加我的项目文件截图,以表明它没有明确说明从何处获取程序集的地方:

【问题讨论】:

  • 当您从 nuget 下载内容时,它会更改您的项目文件,并且也可以更改引用(存储在您的项目文件 *.csproj 中)。如果你编辑你的 *.csproj 文件,你可以在那里找到你项目的所有引用。
  • @Andriy 当然会添加,它是不同的框架,如果您正在为边缘创建扩展,为什么要使用 .net 核心?
  • @Andriy 这就是为什么最好通过 nuget(用于 SDK 和扩展)来完成它 - 它将处理与您的项目/解决方案相关的参考路径,并为从事项目/解决方案的每个人重新创建所有内容.只要确保只签入包配置,而不是包内容,就可以了。
  • @Andriy 也尽量不要将这两种语言放在一起比较,c# 完全是另一回事,你应该这样考虑,学习新东西。它与 c++ 相比的优点/缺点只是一个观点,来自任务的要求。例如 c# 中的垃圾收集和 c++ 中的灵活内存管理。
  • 我确实认为如果您刚开始使用 C#,这是非常深入的。为什么不直接删除重复的程序集并继续前进?当解决方案非常简单时,感觉就像你在试图理解(复杂的)原因时有点被抓住了。

标签: c# uwp .net-core .net-assembly assemblies


【解决方案1】:

这个问题有点糊涂。您需要考虑的一个重要区别是 visual studio 如何引用程序集以及您的编译后的应用程序将如何。

视觉工作室

当您在 Visual Studio 中添加引用时,它会在 csproj 文件中添加一条记录:

<Reference Include="Microsoft.Owin, Version=3.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Owin.3.1.0\lib\net45\Microsoft.Owin.dll</HintPath>
  <Private>True</Private>
</Reference>

上面包括一个“提示路径”。这告诉 Visual Studio 它认为程序集所在的位置。当你编译你的应用程序时,VS 会检查程序集的这个路径。

当您使用 Nuget 安装程序集时。 Nuget 将程序集添加到 packages 文件夹中,并将对该程序集的引用添加到您的 csproj 文件中。带有指向此位置的提示路径。所以VS会在这个位置加载程序集。

编译

当您编译您的应用程序时,其结果是一个可运行的应用程序(dll、exe 等)。这个可运行的应用程序是您的 C# 的机器代码翻译。它包括到程序集的“链接”(DLL 代表 D动态 Link Library)。

bin文件夹

当您编译您的应用程序时,您将在 VS 中的引用上有两个选项:

如果copy localTrue,Visual Studio 将在构建的清单中包含 dll。这基本上意味着 dll 最终会出现在 bin 文件夹中。如果为 false,则不会包含它,并假定应用程序将能够从其他地方引用此程序集。

那么它还能从哪里加载程序集?

您编译的应用程序将根据层次结构查找程序集。它首先会在bin 文件夹中查找与您的清单匹配的程序集。正如我们已经注意到的,尽管程序集并不总是在这里。

如果在此处找不到它,它将检查正在运行的机器以查看它是否可以访问这些程序集。它检查的下一个位置是一个名为Global Assembly Cache 的概念。这是在机器上注册的程序集和程序集位置的寄存器。

如果还是找不到,就会抛出异常。

两个不同版本的程序集链接到我的项目 一会考虑?两者都有?

不,它不能同时使用两者。作为noted in comments,您可以使用alias(es) to reference a particular assembly,但这仍然一次使用一个程序集。

如果您不指定alias,我不希望这会起作用吗?我希望 VS 抱怨它不知道使用哪一个。您可以在 app.config/web.config 中配置程序集重定向:

  <dependentAssembly>
    <assemblyIdentity name="Newtonsoft.Json" culture="neutral" publicKeyToken="30ad4fe6b2a6aeed" />
    <bindingRedirect oldVersion="0.0.0.0-11.0.0.0" newVersion="11.0.0.0" />
  </dependentAssembly>

这会将竞争程序集映射到一个特定版本(通常是最新版本)

【讨论】:

  • 您可以引用两个同名程序集。这就是能够将别名应用于引用的关键。
  • > 你的应用程序甚至编译吗? - 是的,它确实。它确实有效。
  • 是否配置了程序集重定向或别名? @Andriy?
  • 你使用这个程序集还是只是引用它?如果不使用,预编译器会将其从清单中删除。
猜你喜欢
  • 2015-07-07
  • 1970-01-01
  • 1970-01-01
  • 2021-03-13
  • 1970-01-01
  • 2021-06-14
  • 2017-07-10
  • 2019-09-11
  • 1970-01-01
相关资源
最近更新 更多