Azure功能绑定重定向

Mar*_*lie 23 c# assembly-binding-redirect azure-functions visual-studio-2017 azure-functions-runtime

是否可以在azure函数文件夹结构中包含web.config或app.config文件以允许程序集绑定重定向?

Joe*_*aus 25

假设您使用的是最新的(2017年6月)Visual Studio 2017函数工具,我npiasecki第992期发布了一段代码片段,为此提供了一个有点合理的基于配置的解决方案.

如果通过框架管理它是理想的,但至少在配置驱动下你会有更多的变更隔离.我想你也可以使用一些预构建步骤或T4模板来协调项目中的nugets版本(及其依赖项),然后再写出这个配置或生成代码.

所以缺点..

.. BindingRedirects在更新NuGet包时必须记住更新配置(这在app.configs中通常是一个问题).如果需要重定向,您可能还会遇到配置驱动解决方案的问题Newtonsoft.

在我们的例子中,我们使用的是新的Azure Fluent NuGet,它依赖于旧版本,而Microsoft.IdentityModel.Clients.ActiveDirectory不是在特定函数中并排使用的普通ARM管理库版本.

local.settings.json
{
    "IsEncrypted": false,
    "Values": {
        "BindingRedirects": "[ { \"ShortName\": \"Microsoft.IdentityModel.Clients.ActiveDirectory\", \"RedirectToVersion\": \"3.13.9.1126\", \"PublicKeyToken\": \"31bf3856ad364e35\" } ]"
    }
}
Run Code Online (Sandbox Code Playgroud) FunctionUtilities.cs
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Globalization;
using System.Linq;
using System.Reflection;

namespace Rackspace.AzureFunctions
{
    public static class FunctionUtilities
        {
            public class BindingRedirect
            {
                public string ShortName { get; set; }
                public string PublicKeyToken { get; set; }
                public string RedirectToVersion { get; set; }
            }

            public static void ConfigureBindingRedirects()
            {
                var config = Environment.GetEnvironmentVariable("BindingRedirects");
                var redirects = JsonConvert.DeserializeObject<List<BindingRedirect>>(config);
                redirects.ForEach(RedirectAssembly);
            }

            public static void RedirectAssembly(BindingRedirect bindingRedirect)
            {
                ResolveEventHandler handler = null;

                handler = (sender, args) =>
                {
                    var requestedAssembly = new AssemblyName(args.Name);

                    if (requestedAssembly.Name != bindingRedirect.ShortName)
                    {
                        return null;
                    }

                    var targetPublicKeyToken = new AssemblyName("x, PublicKeyToken=" + bindingRedirect.PublicKeyToken)
                        .GetPublicKeyToken();
                    requestedAssembly.Version = new Version(bindingRedirect.RedirectToVersion);
                    requestedAssembly.SetPublicKeyToken(targetPublicKeyToken);
                    requestedAssembly.CultureInfo = CultureInfo.InvariantCulture;

                    AppDomain.CurrentDomain.AssemblyResolve -= handler;

                    return Assembly.Load(requestedAssembly);
                };

                AppDomain.CurrentDomain.AssemblyResolve += handler;
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

  • 对于任何努力完成这项工作的人:如果你有超过1个需要反弹的版本,你将不得不删除AppDomain.CurrentDomain.AssemblyResolve - = handler; 因为这意味着它找到的第一个版本被重定向. (4认同)
  • @ NicholasJ.Markkula本示例中的问题源于以下事实:确定重定向内容的代码正在利用Newtonsoft。因此,如果调用代码的AppDomain已加载Newtonsoft的9.x版本,但是json文件想要重定向到10.x,则该操作将不起作用,因为9.x已加载到AppDomain中,因此无法重定向第一次加载。 (3认同)
  • 谢谢你 对于大多数nuget项目而言,这几乎是必需的。希望他们能尽快解决这个问题。 (2认同)

aka*_*mis 19

刚刚发布了一篇新的博客文章,解释了如何解决问题,看看:

https://codopia.wordpress.com/2017/07/21/how-to-fix-the-assembly-binding-redirect-problem-in-azure-functions/

它实际上是JoeBrockhaus代码的调整版本,即使对于Newtonsoft.Json.dll也能很好地运行


Mik*_*son 6

受公认答案的启发,我认为我会做一个更通用的答案,同时还要考虑升级。

它获取所有程序集,命令它们降序以在顶部获得最新版本,然后在解析时返回最新版本。我自己在静态构造函数中称呼它。

public static void RedirectAssembly()
{
    var list = AppDomain.CurrentDomain.GetAssemblies()
        .Select(a => a.GetName())
        .OrderByDescending(a => a.Name)
        .ThenByDescending(a => a.Version)
        .Select(a => a.FullName)
        .ToList();
    AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
    {
        var requestedAssembly = new AssemblyName(args.Name);
        foreach (string asmName in list)
        {
            if (asmName.StartsWith(requestedAssembly.Name + ","))
            {
                return Assembly.Load(asmName);
            }
        }
        return null;
    };
}
Run Code Online (Sandbox Code Playgroud)

  • OrderByDescending(a =&gt; a.FullName) 将 9.0.0 版本与 10.0.0 版本进行比较可能存在问题。 (2认同)

Dav*_*bbo 3

今天这还不可能直接实现,但我们正在考虑实现这一目标的方法。您能否在https://github.com/Azure/azure-webjobs-sdk-script/issues上打开一个问题,以确保您的具体场景得到关注?谢谢!