【问题标题】:Easy way to pass primitive value to ApiController using AutoFac使用 AutoFac 将原始值传递给 ApiController 的简单方法
【发布时间】:2018-04-12 09:47:57
【问题描述】:

鉴于以下配置 Autofac 的方法:

public class DefaultConfigurationModule : Module
{
    protected override void Load(ContainerBuilder builder)
    {
        builder.RegisterApiControllers(System.Reflection.Assembly.GetExecutingAssembly());
    }
}

并给出以下 Web-Api 控制器:

public class MyController : ApiController
{
    private readonly int _someValue;

    public MyController(int someValue)
    {
        _someValue = someValue;
    }
}

将someValue 传递给MyController 的构造函数的最简单方法是什么?

我可以创建一个MyControllerConfig 类并将其注册到 AutoFac:

public interface IMyControllerConfig
{
    int SomeValue { get; }
}

public class MyControllerConfig : IMyControllerConfig
{
    public int SomeValue { get; set; }

    public MyControllerConfig(int someValue)
    {
        SomeValue = someValue;
    }
}

并将其添加到我的配置模块中:

builder.Register(c => new MyControllerConfig(123)).As<IMyControllerConfig>();

并更改MyApiController 以接受IMyControllerConfig 而不是int:

public class MyController : ApiController
{
    private readonly int _someValue;

    public MyController(IMyControllerConfig myControllerConfig)
    {
        _someValue = myControllerConfig.SomeValue;
    }
}

IMyControllerConfig 接口可能有点矫枉过正;我可以不用MyControllerConfig 就完成了。但是无论哪种方式;整个MyControllerConfig 类似乎将单个(原始)值传递给我的 ApiController 有点过分了。 肯定有更简单、更干净、更整洁的方法吗?

如果这不是 ApiController,我会这样做:

builder.Register(c => new MyClass(123)).As<IMyInterface>();

...只需传入整数。但由于它是 WebApi 控制器,我想/喜欢使用 RegisterApiControllers 方法(因为有很多控制器可以/使用此方法注册就好了) 我似乎把自己画到了一个角落里。并更改MyController,使其不会通过RegisterApiControllers 方法获得'picked up'(例如,通过将其名称更改为不在'Controller' 上结束)并'手动'注册此控制器feels 也有点“脏”。

另一种方法是实现一个依赖解析器并在那里发挥作用,但同样,将单个原语传递给构造函数似乎需要做很多工作。我理解并同意,使用上述方法(使用MyControllerConfig 类)更适合未来的增强和传递更多值而没有太多麻烦,但我不需要它用于这个特定项目。项目中的所有其他 API 控制器都使用无参数构造函数或具有参数接口的构造函数。

请注意,以上示例中的123“const”实际上来自配置文件,只是为了简洁起见;如果它是一个常量,我不需要构造函数参数,可以直接将它放在MyController 类中。

【问题讨论】:

    标签: c# dependency-injection asp.net-web-api2 owin autofac


    【解决方案1】:

    鉴于值是原始的并且它来自配置,推荐的解决方案实际上是使用提供者类型的接口。使用原始构造函数参数(字符串、整数等)存在很多问题,其中一个主要问题是它们非常原始,以至于 [从类型的角度] 无法区分每个参数的实际用途是。在容器中为一个需要连接字符串的类注册一个字符串,其他一些类可能会因为一些不相关的目的而无意中获取它。

    你描述的例子are actually right out of our FAQ on this topic。如果您不能/不会使用 lambda,这是您正在寻找的更简单/更整洁/更清洁的方式,那么提供程序接口是下一个最佳选择。

    请注意,如果您想使用 lambda,则不必更改控制器。

    // Register everything nicely
    builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
    // Override just the one controller
    builder.Register(ctx => new MyController(123)).As<MyController>();
    

    最后获胜,所以当 Web API 尝试解析 MyController 时,它会从 lambda 获取注册。

    【讨论】:

    • Last in wins 这不是依赖于随时可能改变的实现细节吗?编辑:原来是documented....
    • 正确。这是 Autofac(和大多数其他 IoC 容器)的预期行为。
    猜你喜欢
    • 2020-11-25
    • 2016-10-07
    • 2020-01-25
    • 1970-01-01
    • 1970-01-01
    • 2012-08-15
    • 2015-12-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多