使用AutoFac将原始值传递给ApiController的简便方法

时间:2018-04-12 09:47:57

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

给出以下配置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;
    }
}

并将其添加到我的configurationmodule:

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'(例如,将其名称更改为不在'控制器'上结束)并手动注册此控制器'感觉 有点'脏'。

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

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

1 个答案:

答案 0 :(得分:0)

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

您描述的示例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获得注册。