【问题标题】:How to set Web API DependencyResolver when using MVVMLight使用 MVVMLight 时如何设置 Web API DependencyResolver
【发布时间】:2019-01-04 03:55:09
【问题描述】:

我正在使用 OWIN 在使用 galasoft mvvmlight 框架的 wpf 桌面应用程序中自行托管 Web api Web 服务。当我尝试将我的模型数据服务之一依赖注入到 web api 控制器时,我收到一个关于“确保控制器具有无参数的公共构造函数”的错误。

我了解 Web api 控制器不支持开箱即用的依赖注入。我看过很多例子,详细说明了如何在使用 Unity 或编写自己的代码时提供自定义 IDependencyResolver。使用 mvvmlight SimpleIoc.Default 设置 web api 启动类 HttpConfiguration 对象的 DependencyResolver 属性有没有直接的方法?

作为一种解决方法,我目前通过在我的 api 控制器构造函数中调用 SimpleIoc.Default.GetInstance() 来设置我的数据服务。这可行,并且在功能上可能与依赖注入机制相同,但依赖注入似乎更优雅。

public class webApiStartup {
    public void Configuration(IAppBuilder appBuilder)
    {
        // Configure Web API for self-host. 
        HttpConfiguration config = new HttpConfiguration();
        config.Routes.MapHttpRoute(
            name: "FileServerApi",
            routeTemplate: "{controller}/{filename}"
            ,defaults: new { Controller = "filesController" }
        );
//*
//* The Following line of Code does not work. But intellisense suggests
//* that there is a conversion available ?
//*
        config.DependencyResolver = (IDependencyResolver)SimpleIoc.Default;

        appBuilder.UseWebApi(config);
    }
}

//*
//* This constructor for the web api controller works
//* but it is not as elegant as dependency injection
//*
public class filesController : ApiController
{
    ILocalDataService _LocalDataSvc = null;

    public filesController() {
        _LocalDataSvc = SimpleIoc.Default.GetInstance<ILocalDataService>();
    }

【问题讨论】:

    标签: c# mvvm dependency-injection asp.net-web-api2 mvvm-light


    【解决方案1】:

    演员表

     config.DependencyResolver = (IDependencyResolver)SimpleIoc.Default;
    

    将失败,因为SimpleIoc 不是从IDependencyResolver 派生的。

    为派生自IDependencyResolver的容器创建一个包装器

    public class SimpleIocResolver : IDependencyResolver {
        protected ISimpleIoc container;
    
        public SimpleIocResolver(ISimpleIoc container) {
            if (container == null) {
                throw new ArgumentNullException("container");
            }
            this.container = container;
        }
    
        public object GetService(Type serviceType) {
            try {
                return container.GetInstance(serviceType);
            } catch(Exception) {
                return null;
            }
        }
    
        public IEnumerable<object> GetServices(Type serviceType) {
            try {
                return container.GetAllInstances(serviceType);
            } catch (Exception) {
                return new List<object>();
            }
        }
    
        public IDependencyScope BeginScope() {
            return new SimpleIocResolver(container);
        }
    
        public void Dispose() {
            //No Op
        }
    }
    

    并在配置时使用它

    config.DependencyResolver = new SimpleIocResolver(SimpleIoc.Default);
    

    然后可以重构 ApiController

    public class FilesController : ApiController {
        ILocalDataService _LocalDataSvc = null;
    
        public FilesController(ILocalDataService svc) {
            _LocalDataSvc = svc;
        }
    
        //...
    

    前提是依赖已经注册到容器中。

    参考Dependency Injection in ASP.NET Web API 2

    【讨论】:

    • 最好替换默认的IHttpControllerActivator,而不是覆盖DependencyResolver。依赖解析器的问题是它的GetService 方法会强制您在缺少配置(或不正确的配置)时返回 null。这隐藏了错误。这是错误、混乱和挫折的常见来源。只需查看标题为“控制器没有默认构造函数”的所有 SO 问题。使用IHttpControllerActivator 就没有这个问题,因为它需要在调用Create 方法时返回控制器或抛出异常。
    猜你喜欢
    • 2012-04-24
    • 2023-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-22
    相关资源
    最近更新 更多