gpt4 book ai didi

c# - 如何通过覆盖 MSBuild 目标来防止外语资源生成?

转载 作者:太空狗 更新时间:2023-10-29 23:37:55 24 4
gpt4 key购买 nike

我正在致力于减少大型 C#/ASP.NET 解决方案的编译时间。我们的解决方案使用通常的 resx 文件方法翻译成大约十几种外语。这些资源文件的解析和编译大大拖慢了我们的编译时间,是每天的挫折。

我知道可以创建自定义资源提供程序并摆脱 .resx 文件。现在,请假设我们必须坚持使用 .resx 文件。

通过从我们的 .csproj 文件中排除除默认区域设置 .resx 文件之外的所有文件,我能够将编译时间缩短一半。我们的开发人员不需要在日常开发过程中编译十几种其他语言。

我正在寻找防止编译外语 .resx 文件的方法。我提出了两种方法,我正在寻求建议,看哪一种方法更好,或者是否有其他更好的方法。

我想到的两个:

  • 编写可以去除非默认 .resx 文件并重新添加到各种 .csproj 文件中的脚本。也许我们会在版本控制中保留最小的 .csproj 文件,并有一个单独的构建过程来递归地重新添加 .resx 文件,以便重新集成新的翻译、执行测试和进行我们的部署构建。
  • 想出一种方法来覆盖执行 resx 解析和编译的内置 MSBuild 目标,有效地禁用除默认语言之外的所有语言。开发人员可以使用简单的编译标志或构建开关启用/禁用此行为。我还没有深入研究 Microsoft 提供的 .target 文件来了解这个解决方案实际上有多合理或可维护。

更新

我编写了以下 Powershell 脚本,将我所有的外语 EmbeddedResources 和 Compile 元素移动到一个具有 Conditional 属性的新 ItemGroup 中。

$root = "C:\Code\solution_root\"

# Find all csproj files.
$projects = Get-ChildItem -Path $root -Recurse -ErrorAction SilentlyContinue -Filter *.csproj | Where-Object { $_.Extension -eq '.csproj' }

# Use a hashtable to gather a unique list of suffixes we moved for sanity checking - make sure we didn't
# relocate anything we didn't intend to. This is how I caught I was moving javascript files I didn't intend to.
$suffixes = @{}

# Find foreign resources ending in .resx and .Designer.cs
# Use a regex capture to so we can count uniques.
$pattern = "\.(?<locale>\w{2}(-\w{2,3})?\.(Designer.cs|resx))$"

foreach ($project in $projects)
{
"Processing {0}" -f $project.FullName

# Load the csproj file as XML
$xmlDoc = new-object XML
$xmlDoc.Load($project.FullName)

# Set namespace for XPath queries
$ns = New-Object System.Xml.XmlNamespaceManager($xmlDoc.NameTable)
$ns.AddNamespace("ns", $xmlDoc.DocumentElement.NamespaceURI)

$count = 0

$embeds = $xmlDoc.SelectNodes("//ns:EmbeddedResource",$ns)
$compiles = $xmlDoc.SelectNodes("//ns:Compile",$ns)

# Create new conditional ItemGroup node if it does not exist.
# Side-effect - every csproj will get this new element regardless of whether it
# contains foreign resources. That works for us, might not for you.
$moveToNode = $xmlDoc.SelectSingleNode("//ns:ItemGroup[@Condition=`" '`$(Configuration)'=='Release' `"]", $ns)
if ($moveToNode -eq $null) {
# When creating new elements, pass in the NamespaceURI from the parent node.
# If we don't do this, elements will get a blank namespace like xmlns="", and this will break compilation.
# Hat tip to https://stackoverflow.com/questions/135000/how-to-prevent-blank-xmlns-attributes-in-output-from-nets-xmldocument

$conditionAtt = $xmlDoc.CreateAttribute("Condition")
$conditionAtt.Value = " '`$(Configuration)'=='Release' "
$moveToNode = $xmlDoc.CreateElement("ItemGroup", $xmlDoc.Project.NamespaceURI)
$ignore = $moveToNode.Attributes.Append($conditionAtt)
$ignore = $xmlDoc.LastChild.AppendChild($moveToNode)
}

# Loop over the EmbeddedResource and Compile elements.
foreach ($resource in ($embeds += $compiles)) {

# Exclude javascript files which I found in our Web project.
# These look like *.js.resx or *.js.Designer.cs and were getting picked up by my regex.
# Yeah, I could make a better regex, but I'd like to see my kids today.
if ($resource.Include -notmatch "js\.(Designer.cs|resx)$" -and $resource.Include -match $pattern ) {

# We have a foreign-language resource.

# Track unique suffixes for reporting later.
$suffix = $matches['locale']
if (!$suffixes.ContainsKey($suffix)) {
$ignore = $suffixes.Add($suffix,"")
}

$ignore = $moveToNode.InsertBefore($resource, $null)

# Count how many we moved per project.
$count += 1
}
}
"Moved {0} resources in {1}.`n" -f $count, $project.Name
$xmlDoc.Save($project.FullName)
}
echo "The following unique suffixes were processed."
$suffixes.Keys | sort

最佳答案

您可以利用 MSBuild 中的现有机制来处理这种情况,例如 <Choose>元素 documentated here以及引入您自己的构建配置的选项。如果您的开发人员在日常工作中只构建调试配置,您甚至可能不需要自己的构建配置:您可以设置您的项目,以便所有外语资源仅包含在发布构建中。

此项目文件部分将确保仅在 Release 配置中构建波兰语资源(语言代码可能有误,但您明白了):

<Choose>
<When Condition=" '$(Configuration)'=='Release' ">
<ItemGroup>
<EmbeddedResource Include="Properties\Resources.pl.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.pl.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
<Compile Include="Properties\Resources.pl.Designer.cs">
<DependentUpon>Resources.pl.resx</DependentUpon>
<AutoGen>True</AutoGen>
</Compile>

<!-- TODO: add other language resources as necessary-->

</ItemGroup>
</When>
</Choose>

如果您的开发人员需要构建发布配置,您可以创建自己的配置 ReleaseResx 并仅在该配置中包含外语 .resx 文件。

您的两个建议也都行得通,我只是认为这种方法更简洁。

关于c# - 如何通过覆盖 MSBuild 目标来防止外语资源生成?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32323273/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com