如何做“属性注入”和“方法注入”?
目录
先用武侠设定理解:
构造函数注入 = 入门拜师
进入门派时(实例化对象时)
→ 师父会自动把你需要的武功秘籍塞给你。
属性注入 = 练功后发放补充秘籍
对象已经创建好了
→ 门主根据需要给你补发更多秘籍(通过 public 属性)。
方法注入 = 参加某次大会才获得秘籍
某个关键方法被调用时
→ 门主把临时需要的秘籍交给你使用。
- 属性注入(Property Injection)
属性注入指:
DI 容器在对象创建后,会检查是否有可注入的 属性,然后自动填充。
特征:
- 要求属性
public - 必须可写:
set; - 通常要加特性(如
[Inject])
示例:属性注入
public class UserService
{
[Inject]
public ILogger Logger { get; set; } // 容器会注入
public void DoSomething()
{
Logger.Log("UserService working...");
}
}容器内部执行逻辑大概是:
- 先用构造函数创建对象:
var obj = new UserService(); - 反射查找带
[Inject]的属性 - 创建
ILogger实例 obj.Logger = loggerInstance
哪些容器支持属性注入?
| 容器 | 属性注入 |
|---|---|
| ASP.NET Core | 默认容器不支持 |
| Autofac | 支持 |
| Unity | 支持 |
| Dryloc(Prism) | 支持 |
| Ninject | 支持 |
WPF 项目 90% 使用 DryIoc(Prism) → 是支持属性注入的。
- 方法注入(Method Injection)
方法注入指:
调用某个方法时,容器会自动把参数的实例注入进去。
相当于:
“某场关键战斗时,门主在你进场前,把需要的武器塞给你。”
示例:方法注入
public class OrderService
{
[Inject]
public void Init(ILogger logger, ICache cache)
{
logger.Log("Init OrderService");
this._cache = cache;
}
}容器逻辑:
- 对象创建完后
- 找到所有
[Inject]方法 - 分析参数类型
- 调用:
Init(container.Resolve<ILogger>(), container.Resolve<ICache>());哪些容器支持?
| 容器 | 方法注入 |
|---|---|
| ASP.NET Core | 默认容器不支持 |
| Autofac | 支持 |
| Unity | 支持 |
| Dryloc | 支持 |
| Ninject | 支持 |
WPF/Prism/DryIoc → 支持方法注入。
3.属性注入 vs 方法注入 vs 构造函数注入
| 类型 | 用途 | 缺点 | 容器支持度 |
|---|---|---|---|
| 构造函数注入 | 主依赖,高优先级 | 需要改造构造函数 | ★★★★★ |
| 属性注入 | 可选依赖 | 对象不一定完整 | ★★★★☆ |
| 方法注入 | 初始化逻辑 | 反射调用性能略差 | ★★★☆☆ |
4.什么时候使用属性注入?
-
非必须、可选依赖
-
依赖在构造时还不能确定
-
必须 public(WPF ViewModel 常用)
例如:
public class MainViewModel
{
[Inject]
public IUserService UserService { get; set; }
}5.什么时候使用方法注入?
-
初始化需要多参数
-
有顺序要求
-
想做某种“构造时做不到的初始化”
例如 Repository 设置数据库连接:
public class UserRepository
{
private IFreeSql _db;
[Inject]
public void Setup(IFreeSql freeSql)
{
_db = freeSql;
}
}6.一个完整示例(DryIoc / Prism)
public class MyViewModel
{
private ILogger _logger;
public IUserService UserService { get; set; } // 属性注入
[Inject]
public void Init(ILogger logger) // 方法注入
{
_logger = logger;
_logger.Log("ViewModel initialized");
}
}容器在解析 MyViewModel 时:
- 构造函数注入(如果有)
- 属性注入
UserService - 方法注入
Init(logger)
总结
注入方式武侠含义:
- 构造函数注入:入门时必学的基础武功
- 属性注入:后来补给你的额外秘籍
- 方法注入:上阵前临时发的特定武器
三者各有用途,但构造函数注入才是正门武学。
属性/方法注入是辅助手段,WPF 中 ViewModel 常用属性注入。