vNext 中间件抛出 "Unable to locate suitable constructor for type 'XXX'" 错误

vNext middleware throws "Unable to locate suitable constructor for type 'XXX'" error

尝试将某些 OWIN 中间件转换为 vNext 并出现以下错误:

System.InvalidOperationException: Unable to locate suitable constructor for type 'MyMiddleware'. Ensure the type is concrete and all parameters are accepted by a constructor. at Microsoft.Framework.DependencyInjection.ActivatorUtilities.CreateInstance(IServiceProvider provider, Type instanceType, Obje ct[] parameters) at Microsoft.AspNet.Builder.UseMiddlewareExtensions.<>c__DisplayClass1_0.b__0(RequestDelegate next) at Microsoft.AspNet.Builder.ApplicationBuilder.Build() at Microsoft.AspNet.Hosting.HostingEngine.EnsureApplicationDelegate(HostingContext context) at Microsoft.AspNet.Hosting.HostingEngine.Start(HostingContext context)
at Microsoft.AspNet.Hosting.Program.Main(String[] args)

我不知道如何开始调试它。我需要知道 MS 框架试图调用什么排列以及使用什么参数。我如何让它吐出此信息或设置断点?

public class MyMiddleware : AuthenticationMiddleware<MyOptions>
{
     public MyMiddleware(RequestDelegate next,
        IOptions<MyOptions> options,
        ConfigureOptions<MyOptions> configureOptions)
        : base(next, options, configureOptions)
    {
           // doesn't want to call this
    }

    public MyMiddleware(RequestDelegate next,
        IOptions<MyOptions> options,
        ConfigureOptions<MyOptions> configureOptions,
        IDataProtectionProvider dataProtectionProvider,
        ILoggerFactory loggerFactory)
        : base(next, options, configureOptions)
        {
           // doesn't want to call this either and this is the one I'd like to be called
        }
}


public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddOptions();
        services.AddLogging();
        services.AddDataProtection();
    }

    public void Configure(IApplicationBuilder app)
    {
        app.UseErrorPage();

        app.UseMyMiddleware(opts =>
        {
        });
    }
}


public static IApplicationBuilder UseMyMiddleware(this IApplicationBuilder app, Action<MyMiddleware> configureOptions = null, string optionsName = "")
{
    return app.UseMiddleware<MyMiddleware>(
        new ConfigureOptions<MyMiddleware>(configureOptions ?? (o => { }))
        {
            Name = optionsName
        });
}

我尝试在构造函数中四处移动参数,还尝试使用 AuthenticationMiddleware class 的最小参数集创建重载,但出现相同的错误。设置 DNX_TRACE=1 也无法进一步了解问题。

我能够弄清楚如何使用以下步骤 Visual Studio 破解 MS 框架代码:

  1. 转到Debug -> Exception Settings
  2. 展开Common Language Runtime Exceptions并勾选InvalidOperationException
  3. 按照此 article 了解如何调试框架代码。 (非常酷的 2015 年特色)
  4. 在上面的文章中,不是将 sources 设置为源代码的物理位置,而是使用 projects 元素。当您保存 global.json 时,VS 应该刷新解决方案资源管理器并添加与您的解决方案匹配的任何框架项目。对我来说是 Microsoft.Framework.DependencyInjection & Microsoft.Framework.DependencyInjection.Interface。下面是我的 global.json 的样子:

{
"projects": [ "src", "test", "D:/GitHub/DependencyInjection/src" ], // 注意使用正斜杠而不是反斜杠,令人失望;(
"sources": ["packages"],
"sdk":{
"version":“1.0.0-beta4”
}
}

  1. 接下来在您的项目上启动调试器,它不仅会编译您的项目,还会编译您从 github 下载的任何 MS 框架源代码,从而生成必要的框架 .pdb,让您在遇到异常时中断对第 2 步感兴趣。

单步执行 ActivatorUtilities.CreateInstance 代码库后,我发现了问题所在。 Copy/paste 我的扩展方法失败。我在 Action<>ConfigureOptions 参数中使用了 MyMiddleware。将它们更改为 MyOptions 修复了它。