Dáv*_*zky 10 c# msbuild binary compilation roslyn
在构建环境更新后,我们的一个Smoke Tests在TeamCity中爆发.调查结果显示,来自相同的源代码,
什么时候发生
用于重现它的示例代码
static void Main(string[] args)
{
var customerId = Guid.NewGuid();
// Produces buggy code when compiled with MSBuild v14
TestMethodWithParams(args: customerId, whatever: "foo");
//All the calls below result correct behavior, regardless of the version of MSBuild, order and naming of parameters
TestMethodWithParams("foo", customerId);
TestMethodWithParams(whatever: "foo", args: customerId);
TestMethodWithParams(args: new object[] { customerId }, whatever: "foo");
TestMethodWithParams("foo", new object[] { customerId });
TestMethodWithParams(whatever: "foo", args: new object[] {customerId});
}
private static void TestMethodWithParams(string whatever, params object[] args)
{
Console.WriteLine("args: '{0}'", args);
}
Run Code Online (Sandbox Code Playgroud)
究竟发生了什么
不正确的版本只是吞下单个参数,传递null.反编译代码显示了差异:
在正确的二进制:
Guid guid = Guid.NewGuid();
Program.TestMethodWithParams("foo", new object[]
{
guid
});
Run Code Online (Sandbox Code Playgroud)
在二进制文件中:
Guid guid = Guid.NewGuid();
object obj;
Program.TestMethodWithParams("foo", new object[]
{
obj // <- this is and will always be null
});
Run Code Online (Sandbox Code Playgroud)
如何解决它
当我们将单个参数包装到对象数组中时,问题就消失了.另一种选择是不使用命名参数,和/或确保参数的出现顺序在调用和签名中是相同的.
但是:主要问题是我们无法恢复到较旧的MSBuild(...),并且检查整个代码库(并且通过我们的NuGet软件包中的每个二进制文件)也不是一个简单有效的解决方案.而且,这种错误可能会在以后的任何时候意外地重新引入代码库.因此,最好的解决方案可能是以某种方式修复MSBuild.
有没有人经历过这样的事情?可能是MSBuild中的一个错误?想法?