Autofac可以自动自绑定吗?
我知道一些 DI 框架支持这一点(例如 Ninject),但我特别想知道 Autofac。
我希望能够向 Autofac 容器请求一个具体类,并返回一个注入了所有适当构造函数依赖项的实例,无需注册该具体类。即,如果我从未显式绑定它,然后自动将具体类绑定到其自身,就像我调用了builder.Register
ViewModels 就是一个很好的例子,说明何时有用。 在 MVVM 中,分层是这样的:只有 View 依赖于 ViewModel,并且通过松散类型实现,并且您无论如何都不会对 View 进行单元测试。 因此,无需模拟 ViewModel 进行测试,因此没有理由为每个 ViewModel 提供一个接口。 因此,在这种情况下,通常的“注册此接口以解析为此类”的 DI 模式是不必要的复杂性。 在处理像具体类这样简单的事情时,显式自绑定(例如 builder.Register
)也感觉像是一个不必要的步骤。
我知道 Autofac 文档中的基于反射的注册示例,但是那也不合我的口味。 我不希望提前注册每个可能的类的复杂性(和缓慢); 我希望框架能够在我需要时为我提供所需的东西。 约定优于配置,等等。
有没有什么方法可以配置 Autofac,以便它可以说“哦,这是一个具体类型,还没有人注册它,所以我就像它已使用默认设置注册一样”?
I know some DI frameworks support this (e.g. Ninject), but I specifically want to know if it's possible with Autofac.
I want to be able to ask an Autofac container for a concrete class, and get back an instance with all appropriate constructor dependencies injected, without ever registering that concrete class. I.e., if I never bind it explicitly, then automatically bind the concrete class to itself, as if I had called builder.Register<MyClass>();
A good example of when this would be useful is ViewModels. In MVVM, the layering is such that only the View depends on the ViewModel, and that via loose typing, and you don't unit-test the View anyway. So there's no need to mock the ViewModel for tests -- and therefore there's no reason to have an interface for each ViewModel. So in this case, the usual DI pattern of "register this interface to resolve to this class" is unnecessary complexity. Explicit self-binding, like builder.Register<MyClass>();
, also feels like an unnecessary step when dealing with something as straightforward as a concrete class.
I'm aware of the reflection-based registration example in the Autofac docs, but that's not to my taste either. I don't want the complexity (and slowness) of registering every possible class ahead of time; I want the framework to give me what I need when I need it. Convention over configuration, and all that.
Is there any way to configure Autofac so it can say "Oh, this is a concrete type, and nobody registered it yet, so I'll just act like it had been registered with default settings"?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
如果您查看源代码 你会看到 RegisterTypesMatching (和 RegisterTypesFromAssembly)没有做任何反射。 在这种情况下,Autofac 所做的就是注册一个接受或不接受类型的规则。 在上面的示例中,我接受任何属于类的类型。
对于 RegisterTypesFromAssembly,Autofac 注册一条规则,表示“如果您尝试解析的类型具有 Assembly == 指定的程序集,那么我将为您提供一个实例”。
因此:
与直接注册具体类型相比,这将在解析时产生性能影响,因为 Autofac 必须弄清楚例如构造函数的要求。 也就是说,如果您使用默认实例范围(即单例),则仅在第一次解析该类型时才会受到影响。 下次它将使用已经创建的单例实例。
更新:在 Autofac 2 中,有一种更好的方法使容器能够解决任何问题。 这涉及
AnyConcreteTypeNotAlreadyRegistered
注册源。If you look at the source you will see that RegisterTypesMatching (and RegisterTypesFromAssembly) is NOT DOING ANY REFLECTION. All Autofac is doing in this case is registering a rule that accepts a type or not. In my example above I accept any type that is a class.
In the case of RegisterTypesFromAssembly, Autofac registers a rule that says "if the type you're trying to resolve have Assembly == the specified assembly, then I will give you an instance".
So:
Compared to register the concrete types directly, this will have a perf hit at resolve time since Autofac will have to figure out e.g. constructor requirements. That said, if you go with default instance scope, which is singleton, you take the hit only the first time you resolve that type. Next time it will use the already created singleton instance.
Update: in Autofac 2 there is a better way of making the container able to resolve anything. This involves the
AnyConcreteTypeNotAlreadyRegistered
registration source.怎么样:
没有进行反射,正如 Peter Lillevold 指出< /a>.
what about:
no reflection is done, as Peter Lillevold points out.