我想在单元测试中访问一个MSBUILD变量,该变量是.NET 4.5 class Library Project(Classic CSPROJ(,但是我未能找到任何文章讨论一种传递值的方法从MSBUILD到执行上下文。
我考虑过在编译过程中设置环境变量,然后在执行过程中读取该环境变量,但这似乎需要一个自定义任务来设置环境变量值,我有点担心该变量的范围(理想情况下,我只希望它可用于当前执行的项目,而不是全球(。
是否有已知的解决方案可以从运行时从DLL项目内部读取MSBUILD属性?在执行过程中,可以"通过参数将MSBUILD属性"?
我最终通过使用.NET核心项目中默认使用的相同代码生成任务使其起作用。唯一的区别是,我必须在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
的线条在那里可以很好地发挥干净的作用(请参阅上面的评论中的链接答案(。其他一切都应该足够直观。
当项目编译时,将自定义属性添加到程序集中,然后我可以使用正常反射检索:
Assembly
.GetExecutingAssembly()
.GetCustomAttribute<SolutionFileAttribute>()
.SolutionFile
这真的很好,让我避免对解决方案文件进行任何硬编码搜索。
我认为您有几个选择:
- 使用环境变量,就像您已经建议的那样。可能需要进行自定义任务,但是很容易做到,而您的任何额外组件都没有。所需的全球可见性可能是一个艰难的问题;例如,考虑在CI机器上构建并行的。
- 在构建过程中写一个代码片段,并将其包含在您的结果中(类似于您在评论中建议的链接中已经找到的内容。
- 在构建过程中编写一个文件(甚至是app.config(,其中包含反映您需要拥有的MSBUILD属性的设置;在测试过程中阅读这些内容。
(顺便说一句,毫无意义,是尝试在运行时再次读取MSBUILD项目文件(使用Microsoft.build框架(。对于一开始,这是一大笔钱,因为几乎没有增益IMHO。更重要的是,您很可能 - 取决于您属性的复杂性和依赖性 - 需要确保您调用具有与实际构建过程中存在的属性相同属性的MSBUILD库。可以说,这可能会让您退缩。(
最后两个选项最适合,因为它们具有相等的特征:它们仅范围范围为您当前拥有的构建/测试运行(即,您可以在没有干扰的情况下进行并行运行构建(。
我可能会去第三,因为这似乎是最容易实现的。
实际上,我在一个我一直在研究的较大项目上做到了这一点。基本上,我们有不同的环境(数据库连接字符串等(,并且会选择这些环境作为帖子构建步骤,基本上将特定的myenv.config
复制到default.config
。测试只会寻找一个名为default.config
的文件,然后在其中设置了任何设置。
另一个版本,从几个Internet源编译,在构建时获取环境变量,然后在代码
中使用其值file assemblyAttribute.cs
namespace MyApp
{
[AttributeUsage(AttributeTargets.Assembly)]
public class MyCustomAttribute : Attribute
{
public string Value { get; set; }
public MyCustomAttribute(string value)
{
Value = value;
}
}
}
文件mainform.cs
var myvalue = Assembly.GetExecutingAssembly().GetCustomAttribute<MyCustomAttribute>().Value;
文件myApp.csproj,最后(build for Build in build instrate solutionInfo.cs文件中获取%username%环境变量,自动包含它以构建(
( <Target Name="BeforeBuild">
<ItemGroup>
<AssemblyAttributes Include="MyApp.MyCustomAttribute">
<_Parameter1>$(USERNAME)</_Parameter1>
</AssemblyAttributes>
</ItemGroup>
<WriteCodeFragment AssemblyAttributes="@(AssemblyAttributes)" Language="C#" OutputFile="SolutionInfo.cs">
<Output TaskParameter="OutputFile" ItemName="Compile" />
<Output TaskParameter="OutputFile" ItemName="FileWrites" />
</WriteCodeFragment>
</Target>