如何使用Microsoft.Extensions.DependencyInjection在.NET Framework的WebAPI中进行依赖注入?

5
我正在尝试按照以下步骤,将我的日志记录器作为依赖项注入到一个.NET Framework 4.7.2 Web API 项目中:https://scottdorman.blog/2016/03/17/integrating-asp-net-core-dependency-injection-in-mvc-4/
在MVC Web应用程序中这很好用,但在WebAPI项目中则会出现“缺少无参数构造函数”错误。
如何使用默认的 Microsoft.Extensions.DependencyInjection程序集成功注入框架?
public class Startup
{
    public void Configuration(IAppBuilder app)
    {

        var services = new ServiceCollection();
        ConfigureServices(services);
        var resolver = new DefaultDependencyResolver(services.BuildServiceProvider());
        DependencyResolver.SetResolver(resolver);
    }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllersAsServices(typeof(Startup).Assembly.GetExportedTypes()
            .Where(t => !t.IsAbstract && !t.IsGenericTypeDefinition)
            .Where(t => typeof(IController).IsAssignableFrom(t)
                        || t.Name.EndsWith("Controller", StringComparison.OrdinalIgnoreCase)));
        services.AddSingleton<IMyInterface , MyClass>();
    }
}
public class DefaultDependencyResolver : IDependencyResolver
{
    protected IServiceProvider serviceProvider;

    public DefaultDependencyResolver(IServiceProvider serviceProvider)
    {
        this.serviceProvider = serviceProvider;
    }

    public object GetService(Type serviceType)
    {
        return this.serviceProvider.GetService(serviceType);
    }

    public IEnumerable<object> GetServices(Type serviceType)
    {
        return this.serviceProvider.GetServices(serviceType);
    }
}

public static class ServiceProviderExtensions
{
    public static IServiceCollection AddControllersAsServices(this IServiceCollection services,
        IEnumerable<Type> controllerTypes)
    {
        foreach (var type in controllerTypes)
        {
            services.AddTransient(type);
        }

        return services;
    }
}

使用类似这样的注入方式时出现“缺少无参构造函数”错误:
private IMyInterface _my;
public HomeController(IMyInterface my)
{
    _my= my;
}

现在看到您如何将 IMyInterface 注册到服务集合中。 - Nkosi
你还没有为 Web API 注册依赖项解析。 - Nkosi
请查看更新的代码。 - user8808262
请问您能详细解释一下“您还没有为Web API注册依赖项解析器”的意思吗?我应该在哪里进行这个操作? - user8808262
2个回答

11

注册说明

一个问题是你正在使用MVC解析器注册API来注册DependencyResolver,但不幸的是与WebAPI解析器注册API不同。相反,你想要做的是:

public void Configuration(IAppBuilder app)
{    
    var services = new ServiceCollection();
    ConfigureServices(services);
    var resolver = new DefaultDependencyResolver(services.BuildServiceProvider());
    HttpConfiguration config = new HttpConfiguration();
    config.DependencyResolver = resolver;
    app.UseWebApi(config);
}

请注意,IDependencyResolver接口在System.Web.Http中单独定义, 因此您的DefaultDependencyResolver类需要更新以从中派生。

该接口上的一个变化是引入了BeginScope API。要实现它,请调用Microsoft.Extensions.DependencyInjection中公开的IServiceProvider上的CreateScope扩展方法获取一个新作用域。然后将该作用域中的提供程序传递给新的DefaultDependencyResolver实例。

    public IDependencyScope BeginScope()
    {
        return new DefaultDependencyResolver(this.serviceProvider.CreateScope().ServiceProvider);
    }

完整示例

你在遵循MVC的博客示例时使用了OWIN。当我尝试创建一个完整的示例时,我遇到了与你相同的错误,这是因为我没有正确配置OWIN,所以Startup从未被调用。下面是一个完整可工作的示例,演示了如何使用Microsoft.Extensions.DependencyInjection来注入MVC和WebAPI控制器:

https://github.com/ryandle/MVC_WebApi_DI_Example


谢谢,这很有帮助。虽然我似乎没有通过上面的方法得到任何不同的结果。它仍然期望在控制器上有无参数的构造函数。我需要在BeginScope()中配置一些东西吗?(预计使用System.Web.Http.Dependencies.IDependencyResolver来实现) public IDependencyScope BeginScope() { throw new NotImplementedException(); } - user8808262
@user8808262,我已对实现BeginScope()进行了澄清。看一下,如果您有更多问题,请告诉我。 - RyanY
@RyanY,谢谢你的帮助。我按照你上面的建议添加了CreateScope来获取新的作用域,但是还是出现了缺少无参构造函数的错误。你有什么其他的想法吗?谢谢!如果你有相关的代码,能否在这里分享一下呢?或许那会对我有所帮助。谢谢。 - user8808262
@user8808262在我的回答中添加了一个完整的示例,希望这会有所帮助! - RyanY
@user8808262 没问题。如果这完全回答了你的问题,请将其标记为解决!否则,我们继续完善答案。 - RyanY
显示剩余2条评论

-4

你在HomeController上使用了[Serializable]吗?如果是的话,在使用它时,你需要一个没有参数的构造函数。

尝试添加这个:public HomeController() { } 然后再运行。

更多信息:无参数构造函数错误


不行。但是如果我添加public HomeController() { },那么我的记录器就没有在构造函数中配置/注入。 - user8808262

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