汇编重映射无效。

8
我在使用VS2015 RC编译项目时,出现了错误代码为MSB3277的提示。完整提示如下:

1>C:\Program Files (x86)\MSBuild\14.0\bin\Microsoft.Common.CurrentVersion.targets(1819,5): warning MSB3277: Found conflicts between different versions of the same dependent assembly that could not be resolved. These reference conflicts are listed in the build log when log verbosity is set to detailed.

我改变了输出设置,并将其详细化,以便查看具体情况。
我的app.config文件如下:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="System.Net.Primitives" culture="neutral" publicKeyToken="b03f5f7f11d50a3a" />
        <bindingRedirect oldVersion="3.9.0.0" newVersion="4.0.0.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
</configuration>

更详细的错误信息如下:

2> 考虑在 app.config 中重新映射程序集 "System.Net.Primitives, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",将其从版本 "3.9.0.0" [] 映射到版本 "4.0.0.0" [C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\MonoAndroid\v1.0\Facades\System.Net.Primitives.dll],以解决冲突并消除警告。

app.config 绑定中,我尝试了使用 0.0.0.0-4.0.0.0 作为 oldVersion 和指定精确的 oldVersion,但两者都导致相同的结果。
当我查看 System.Net.Http.Primitives 的属性时,显示如下信息:
  • 运行时版本: v4.0.30319
  • 版本: 1.5.0.0
这是一个 Xamarin 项目,如果相关的话。

你解决了这个错误吗? - Beetee
@Beetee 目前还没有。不过我在过去几个月里没有做太多的 Xamarin 工作。 - Nikola
我在 Xamarin 项目中也遇到了这个错误。我的做法有点激进,但它起作用了。我重新安装了 Update-Package -reinstall 包。请参阅如何重新安装包 - Eli
@Elisa,你提供的URL返回404错误。这个问题发生在两年前,当时我没能解决它。现在项目已经消失了,所以我甚至无法测试你的建议 :/ - Nikola
@Nikola 对不起,我的错误!这是链接 https://learn.microsoft.com/en-us/nuget/consume-packages/reinstalling-and-updating-packages。对于可能遇到相同问题的人可能会有用。 - Eli
如果这个问题无法再现,那么是时候关闭或删除它了。 - Lex Li
1个回答

0

当你有不同版本的相同NuGet时,程序集绑定是一场噩梦。我在遇到类似问题时使用了三种方法。

  1. 合并NuGet包。尽可能安装最新的和缺失的。
  2. 从代码中删除所有"assemblyBinding"部分,并重新安装所有NuGet包以获得当前设置的干净版本。
  3. 使用自定义MSBuild任务来解决问题,但你真的不想使用它。如果你可以将项目迁移到.NET Core库或只是.NET SDK,请这样做。我不得不强制重新映射所有内容,因为我有100多个旧的.NET Framework绑定项目,无法轻松迁移。维护是一场噩梦,所以我创建了一个基于MSBuild的任务。
namespace YourNamespace.Sdk
{
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Reflection;
    using System.Text;
    using System.Xml.Linq;
    using Microsoft.Build.Framework;
    using Microsoft.Build.Utilities;

    public class GenerateConfigBindingRedirects : Task
    {
        public string ConfigFilePath { get; set; }

        public ITaskItem[] SuggestedBindingRedirects { get; set; }

        public override bool Execute()
        {
            if (this.SuggestedBindingRedirects == null || this.SuggestedBindingRedirects.Length == 0)
            {
                return true;
            }

            var doc = XDocument.Load(this.ConfigFilePath);

            if (doc == null)
            {
                return false;
            }

            var runtimeNode = doc.Root.Nodes().OfType<XElement>().FirstOrDefault(e => e.Name.LocalName == "runtime");

            if (runtimeNode == null)
            {
                runtimeNode = new XElement("runtime");
                doc.Root.Add(runtimeNode);
            }
            else
            {
                return false;
            }

            var ns = XNamespace.Get("urn:schemas-microsoft-com:asm.v1");

            var redirectNodes = from redirect in this.ParseSuggestedRedirects()
                                select new XElement(
                                        ns + "dependentAssembly",
                                        new XElement(
                                            ns + "assemblyIdentity",
                                            new XAttribute("name", redirect.Key.Name),
                                            new XAttribute("publicKeyToken", GetPublicKeyToken(redirect.Key.GetPublicKeyToken())),
                                            new XAttribute("culture", string.IsNullOrEmpty(redirect.Key.CultureName) ? "neutral" : redirect.Key.CultureName)),
                                        new XElement(
                                            ns + "bindingRedirect",
                                            new XAttribute("oldVersion", "0.0.0.0-" + redirect.Value),
                                            new XAttribute("newVersion", redirect.Value)));

            var assemblyBinding = new XElement(ns + "assemblyBinding", redirectNodes);

            runtimeNode.Add(assemblyBinding);
            using (var stream = new StreamWriter(this.ConfigFilePath))
            {
                doc.Save(stream);
            }

            return true;
        }

        private static string GetPublicKeyToken(byte[] bytes)
        {
            var builder = new StringBuilder();
            for (var i = 0; i < bytes.GetLength(0); i++)
            {
                builder.AppendFormat("{0:x2}", bytes[i]);
            }

            return builder.ToString();
        }

        private IDictionary<AssemblyName, string> ParseSuggestedRedirects()
        {
            var map = new Dictionary<AssemblyName, string>();
            foreach (var redirect in this.SuggestedBindingRedirects)
            {
                try
                {
                    var maxVerStr = redirect.GetMetadata("MaxVersion");
                    var assemblyIdentity = new AssemblyName(redirect.ItemSpec);
                    map.Add(assemblyIdentity, maxVerStr);
                }
                catch
                {
                }
            }

            return map;
        }
    }
}

namespace YourNamespace.Sdk
{
    using System.IO;
    using System.Linq;
    using System.Xml.Linq;
    using Microsoft.Build.Utilities;

    public class RemoveRuntimeNode : Task
    {
        public string ConfigFilePath { get; set; }

        public override bool Execute()
        {
            var doc = XDocument.Load(this.ConfigFilePath);

            if (doc == null)
            {
                return false;
            }

            doc.Root.Nodes().OfType<XElement>().FirstOrDefault(e => e.Name.LocalName == "runtime")?.Remove();

            using (var stream = new StreamWriter(this.ConfigFilePath))
            {
                doc.Save(stream);
            }

            return true;
        }
    }
}

来自 csproj 文件:

<?xml version="1.0" encoding="utf-8" ?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  
  <ItemGroup>
    <PackageReference Include="Microsoft.Build.Tasks.Core" Version="16.4.0" />
  </ItemGroup>

  <UsingTask TaskName="RemoveRuntimeNode" AssemblyFile="$([MSBuild]::ValueOrDefault('$(YourLibPath)', '$(MSBuildThisFileDirectory)..\lib\netstandard2.0\YourNamespace.Sdk.dll'))" />

  <UsingTask TaskName="GenerateConfigBindingRedirects" AssemblyFile="$([MSBuild]::ValueOrDefault('$(YourLibPath)', '$(MSBuildThisFileDirectory)..\lib\netstandard2.0\YourNamespace.Sdk.dll'))" />

  <Target Name="RemoveConfigRuntimeNode" BeforeTargets="ResolveAssemblyReferences" Condition="Exists('$(MSBuildProjectDirectory)\app.config')">
    <RemoveRuntimeNode ConfigFilePath="$(MSBuildProjectDirectory)\app.config" />
  </Target>

  <Target Name="GenerateConfigBindingRedirects" AfterTargets="RemoveConfigRuntimeNode" Condition="Exists('$(MSBuildProjectDirectory)\app.config')">
    <GenerateConfigBindingRedirects ConfigFilePath="$(MSBuildProjectDirectory)\app.config" SuggestedBindingRedirects="@(SuggestedBindingRedirects)"/>
  </Target>
</Project>

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