如何在运行时读取给定项目中的 MSBuild 属性?
How to read a MSBuild property in a given project in runtime?
我想在单元测试中访问 MSBuild 变量,这是一个 .NET 4.5 class 库项目 (classic csproj),但我找不到任何讨论方法的文章将值从 MSBuild 传递到执行上下文中。
我考虑过在编译期间设置一个环境变量,然后在执行期间读取该环境变量,但这似乎需要一个自定义任务来设置环境变量值,我有点担心变量的范围(理想情况下,我只希望它对当前正在执行的项目可用,而不是全局可用。
是否有在运行时从 DLL 项目内部读取 MSBuild 属性 的已知解决方案? MSBuild 属性可以在执行期间以某种方式 "passed as parameters" 吗?
我想你有几个选择:
- 使用环境变量,就像您已经建议的那样。执行此操作可能需要自定义任务,但它是 easy to do,您不需要任何额外的程序集。所需的全球知名度可能是一个棘手的问题;例如,考虑在 CI 机器上并行构建。
- 在构建期间编写代码片段并将其包含到生成的程序集中(类似于您在评论中建议的 the link 下已经找到的内容。
- 在构建期间编写一个文件(甚至 app.config),其中包含反映您需要的 MSBuild 属性的设置;在测试期间阅读那些 运行s.
(顺便说一句,没有意义的是,尝试在 运行 时间内再次读取 MSBuild 项目文件(使用 Microsoft.Build 框架)。这一次需要大量工作首先,恕我直言,收益微乎其微。
更重要的是,您很可能(取决于属性的复杂性和依赖性)需要确保您调用的 MSBuild 库具有与实际生成期间存在的相同属性。可以说,如果你是从这里开始的,那可能会让你退缩。)
最后两个选项最适合,因为它们具有相同的特征:它们的范围仅限于您当前拥有的 build/test 运行(即您可以并行 运行ning 构建无干扰)。
我可能会选择第三个,因为这似乎是最容易实现的。
事实上,我已经在我一直从事的一个更大的项目中这样做了。基本上,我们有不同的环境(数据库连接字符串等)并且 select 那些
作为 post 构建步骤,基本上将特定的 myenv.config
复制到 default.config
。
测试只会查找名为 default.config
的文件并获取其中设置的任何设置。
我最终通过使用 .Net Core 项目中默认使用的相同代码生成任务使其工作。唯一的区别是我必须在 csproj 文件中手动添加 Target
才能工作,因为代码创建不是框架项目的标准:
<Target Name="BeforeBuild">
<ItemGroup>
<AssemblyAttributes Include="MyProject.SolutionFileAttribute">
<_Parameter1>$(SolutionPath)</_Parameter1>
</AssemblyAttributes>
</ItemGroup>
<WriteCodeFragment AssemblyAttributes="@(AssemblyAttributes)" Language="C#" OutputDirectory="$(IntermediateOutputPath)" OutputFile="SolutionInfo.cs">
<Output TaskParameter="OutputFile" ItemName="Compile" />
<Output TaskParameter="OutputFile" ItemName="FileWrites" />
</WriteCodeFragment>
</Target>
带有 Compile
和 FileWrites
的行可以很好地处理 clean 等(请参阅我上面评论中的链接答案)。其他一切都应该足够直观。
当项目编译时,一个自定义属性被添加到程序集中,然后我可以使用普通反射检索:
Assembly
.GetExecutingAssembly()
.GetCustomAttribute<SolutionFileAttribute>()
.SolutionFile
这非常有效,让我可以避免对解决方案文件进行任何硬编码搜索。
我想在单元测试中访问 MSBuild 变量,这是一个 .NET 4.5 class 库项目 (classic csproj),但我找不到任何讨论方法的文章将值从 MSBuild 传递到执行上下文中。
我考虑过在编译期间设置一个环境变量,然后在执行期间读取该环境变量,但这似乎需要一个自定义任务来设置环境变量值,我有点担心变量的范围(理想情况下,我只希望它对当前正在执行的项目可用,而不是全局可用。
是否有在运行时从 DLL 项目内部读取 MSBuild 属性 的已知解决方案? MSBuild 属性可以在执行期间以某种方式 "passed as parameters" 吗?
我想你有几个选择:
- 使用环境变量,就像您已经建议的那样。执行此操作可能需要自定义任务,但它是 easy to do,您不需要任何额外的程序集。所需的全球知名度可能是一个棘手的问题;例如,考虑在 CI 机器上并行构建。
- 在构建期间编写代码片段并将其包含到生成的程序集中(类似于您在评论中建议的 the link 下已经找到的内容。
- 在构建期间编写一个文件(甚至 app.config),其中包含反映您需要的 MSBuild 属性的设置;在测试期间阅读那些 运行s.
(顺便说一句,没有意义的是,尝试在 运行 时间内再次读取 MSBuild 项目文件(使用 Microsoft.Build 框架)。这一次需要大量工作首先,恕我直言,收益微乎其微。 更重要的是,您很可能(取决于属性的复杂性和依赖性)需要确保您调用的 MSBuild 库具有与实际生成期间存在的相同属性。可以说,如果你是从这里开始的,那可能会让你退缩。)
最后两个选项最适合,因为它们具有相同的特征:它们的范围仅限于您当前拥有的 build/test 运行(即您可以并行 运行ning 构建无干扰)。
我可能会选择第三个,因为这似乎是最容易实现的。
事实上,我已经在我一直从事的一个更大的项目中这样做了。基本上,我们有不同的环境(数据库连接字符串等)并且 select 那些
作为 post 构建步骤,基本上将特定的 myenv.config
复制到 default.config
。
测试只会查找名为 default.config
的文件并获取其中设置的任何设置。
我最终通过使用 .Net Core 项目中默认使用的相同代码生成任务使其工作。唯一的区别是我必须在 csproj 文件中手动添加 Target
才能工作,因为代码创建不是框架项目的标准:
<Target Name="BeforeBuild">
<ItemGroup>
<AssemblyAttributes Include="MyProject.SolutionFileAttribute">
<_Parameter1>$(SolutionPath)</_Parameter1>
</AssemblyAttributes>
</ItemGroup>
<WriteCodeFragment AssemblyAttributes="@(AssemblyAttributes)" Language="C#" OutputDirectory="$(IntermediateOutputPath)" OutputFile="SolutionInfo.cs">
<Output TaskParameter="OutputFile" ItemName="Compile" />
<Output TaskParameter="OutputFile" ItemName="FileWrites" />
</WriteCodeFragment>
</Target>
带有 Compile
和 FileWrites
的行可以很好地处理 clean 等(请参阅我上面评论中的链接答案)。其他一切都应该足够直观。
当项目编译时,一个自定义属性被添加到程序集中,然后我可以使用普通反射检索:
Assembly
.GetExecutingAssembly()
.GetCustomAttribute<SolutionFileAttribute>()
.SolutionFile
这非常有效,让我可以避免对解决方案文件进行任何硬编码搜索。