.net依赖注入框架 Autofac和MEF的对比
Autofac 默认需要显式注册每个类型,这是它与MEF在模块化设计上的主要区别。以下是具体对比说明:
1. Autofac 的基本注册方式
Autofac 必须通过代码明确注册每个需要注入的类型(除非使用特殊扫描机制):
var builder = new ContainerBuilder();
// 必须手动注册每个类型
builder.RegisterType<ServiceA>().As<IService>();
builder.RegisterType<ServiceB>().As<IService>();
builder.RegisterType<ViewModel>().AsSelf();
var container = builder.Build();
2. 与MEF的关键差异
特性 | Autofac | MEF |
---|---|---|
注册方式 | 显式注册(代码定义) | 隐式注册(通过[Export] 特性标记) |
模块发现 | 需手动扫描或配置 | 自动扫描程序集发现导出项 |
动态加载 | 需额外处理(如Assembly.Load ) | 原生支持DirectoryCatalog 动态加载 |
松散耦合 | 依赖接口但需注册 | 仅需约定接口,无需注册 |
3. Autofac的替代方案(接近MEF的行为)
如果希望在Autofac中实现类似MEF的自动发现,可以通过以下方式:
方案1:程序集扫描(仍需显式定义规则)
builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly()).Where(t => t.Name.EndsWith("Service")).AsImplementedInterfaces();
方案2:配合Microsoft.Composition
(MEF2)
// 需引用System.Composition
var configuration = new ContainerConfiguration().WithAssembly(typeof(ModuleA).Assembly);
var container = configuration.CreateContainer();
4. 何时选择Autofac?
- 需要精细控制生命周期(如单例/实例作用域)
- 需要更快的解析性能(Autofac的解析通常比MEF快)
- 项目已深度集成其他DI功能(如AOP、属性注入)
5. 代码示例对比
假设有一个模块包含View
和ViewModel
:
// MEF方式(自动发现)
[Export(typeof(IModule))]
public class MyModule {[Export] public ViewModelA { get; set; } // 自动导出
}// Autofac方式(需手动注册)
builder.RegisterType<MyModule>().As<IModule>();
builder.RegisterType<ViewModelA>().AsSelf(); // 必须显式注册
总结来说,如果您追求完全的模块化和自动发现,MEF更合适;如果需要精细控制和性能优化,Autofac更优。两者也可以通过System.Composition
(MEF2)与Autofac结合使用。