C# 输出程序集文件名 (csproj)

7
有没有办法在使用VS构建时更改输出程序集文件名?
我有两个配置(包括Debug / Release分支),具有略有不同的功能,应该以不同的方式使用,但应保留在相同目录中。因此,最好的方案是ProjectName.dll和ProjectName.Test.dll。
请不要建议更改AssemblyName参数(这是我通过谷歌SO看到的唯一提示),它们并不相同。 AssemblyName还会更改每个类的完整类名,这是不希望发生的。我只想更改文件名,保持程序集内部任何内容不变。
现在,我已经通过在.csproj中添加AfterBuild目标来复制文件并重命名来完成了此操作,但我不喜欢这种解决方案。会不会更容易?
也尝试将OutputPath设置为SomeWhere \ ProjectName.Test.dll-它只是创建了ProjectName.Test.dll目录并将$(AssemblyName).dll放置在那里。
更新:更清晰的说明,为什么AssemblyName更改不是我想要的。 AssemblyName也是程序集中每个类型的一部分(它指向程序集,从中找到类型),并直接应用于类型解析。例如,我引用ISome接口的ProgName.dll。解析器尝试查找ProgName(作为类型元数据中设置的值),但找不到任何内容,因为没有ProgName,只有ProgName.Test。当它们都具有AssemblyName ProgName(而不是.Test时),它将起作用。当然,如果我处理不同的文件名。
更新2:关于我在谈论AssemblyName时所说的内容的更好解释:Resolver data screenshot 红色标记是程序集解析器尝试查找的内容。我的两个配置中都有相同的接口,因此客户端不应关心他需要查找哪个程序集。两者都应具有相同的AssemblyName,但具有不同的文件名(以存储在同一文件夹中)。
我使用ILRepack将多个程序集合并为一个:
  • A.dll
  • B.dll(或B.Test.dll,取决于配置)
  • C.dll
A和C都引用B.dll。如果我合并B.Test.dll(以AssemblyName“B.Test”)引用将保持不变。如果我合并B.dll,则不会留下任何引用(所有代码内部)。因此,我需要B.Test.dll(具有此文件名)具有AssemblyName“B”。

你能解释一下“更改AssemblyName会更改完整类名”的情况吗?如果我通过VS(项目> <project>属性>应用程序> Assembly名称)或通过手动更改csproj文件(AssemblyName属性)来更改程序集名称,我的现有命名空间和类名仍然保持不变。同时,“默认命名空间”属性也不会改变(在csproj中的RootNamespace)。你可能安装了某个扩展程序,当程序集名称更改时同步根命名空间吗? - Luc
如果只需要重命名,那么你到底不喜欢使用后构建脚本的哪一点呢? - blins
1
Luc,https://msdn.microsoft.com/en-us/library/system.type.assemblyqualifiedname(v=vs.110).aspx 完整的类型名称包括程序集名称,用于解析类型的程序集(给定类型所在的程序集)。更改程序集名称会导致不同的类型解析问题,我可以修复它们,但最好避免这样做。 - rattler
khlr,请仔细阅读问题。我说过,更改AssemblyName不是答案,并解释了原因。你能给出其他建议吗?重申一遍:我不想更改程序集的标识本身。我只想在构建期间更改csc写入文件的文件名。 - rattler
好的,根据您更新后的问题,我很清楚您想要什么。不幸的是,我没有看到任何其他(即时)方法,只能复制/重命名创建的dll。话虽如此,在MSBuild过程中有大量的钩子。可能有一个“计算”程序集文件名以及其标识的钩子。如果您想走这条路,那么MSBuild参数“/pp[:filepath]”就是您的朋友。这会输出您的csproj,并将每个导入内联,您可以进行分析。明智之言,不要使用此生成的文件进行调试/构建(我已经在这个VS错误上花费了太多时间)。 - Luc
显示剩余3条评论
1个回答

8

仅为说明Luc在评论中提到的内容:您可以轻松地调整csproj文件中的一些行,达到您所寻求的效果。

请参考以下示例:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
  <PropertyGroup>
    <someProps>....</someProps>
    <RootNamespace>Your.Project</RootNamespace> <!-- Your project namespace stays the same -->
    <AssemblyName>Your.Project</AssemblyName>
    <someMoreProps>...</someMoreProps>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <PlatformTarget>AnyCPU</PlatformTarget>
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <OutputPath>bin\Debug\</OutputPath>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
    <AssemblyName>Your.Project.Foo</AssemblyName> <!-- you could simply "override" the resulting assembly name -->
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <samePropsAsAbove>...</samePropsAsAbove>
    <AssemblyName>Your.Project.Bar</AssemblyName> <!-- you could do this on a per-configuration-basis -->
  </PropertyGroup>
  ...

通过这样做,你只是改变了输出文件的名称。因此,在这个例子中,输出文件(使用调试配置)将是Your.Project.Foo.dll,而不是默认的Your.Project.dll
这并不会改变任何类名或你所假定的命名空间。

现在误解发生了。我从来没有假设当我改变AssemblyName时,类名或命名空间会发生变化。我指的是类的元数据。当我们尝试创建实例的时候 - rattler
哎呀。...当我们尝试从“重命名”程序集创建类的实例时,程序集解析器会搜索哪个dll? - rattler
请问您能否再次更新您的问题,并发布一段代码片段,展示您如何使用解析器?我认为这将有助于更好地帮助您 :) - Jan Köhler

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接