程序集的重新映射不起作用

本文关键字:映射 不起作用 新映射 程序集 | 更新日期: 2023-09-27 18:18:44

当我在VS2015 RC中构建我的项目时,我得到了MSB3277错误代码。完整的信息是:

1> C: '程序文件(x86) ' [' 14.0 ' bin ' Microsoft.Common.CurrentVersion.targets (1819 5):的不同版本之间存在冲突无法解析的相同从属程序集。这些参考当日志详细度设置为时,冲突将在构建日志中列出详细。

所以我这样做了,我把我的输出更改为详细,看看发生了什么。

我的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>考虑重新映射程序集"System.Net.Primitives,文化=中性,PublicKeyToken=b03f5f7f11d50a3a"从版本"3.9.0.0"[]版本"4.0.0.0" [C:'Program Files (x86)'Reference微软组件' ' Framework ' MonoAndroid ' v1.0 '外墙' 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项目。

程序集的重新映射不起作用

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

  1. NuGet包的整合。如果可能,安装最新的和丢失的。
  2. 删除所有的assemblyBinding",并重新安装所有NuGet包,以获得当前安装的干净版本。
  3. 使用自定义MSBuild任务来解决问题,但你真的不想使用它。如果你可以将你的项目迁移到。net Core库或。net SDK,那就去做吧。我不得不重新映射它,因为我有100多个项目与旧的。net框架绑定,我不能轻易迁移。维护是一场噩梦,所以我创建了一个基于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>