如何在运行时读取给定项目中的MSBuild属性



我想在单元测试中访问一个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>

CompileFileWrites的线条在那里可以很好地发挥干净的作用(请参阅上面的评论中的链接答案(。其他一切都应该足够直观。

当项目编译时,将自定义属性添加到程序集中,然后我可以使用正常反射检索:

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>

最新更新