目录

如何做“属性注入”和“方法注入”?

先用武侠设定理解:

构造函数注入 = 入门拜师

进入门派时(实例化对象时)
→ 师父会自动把你需要的武功秘籍塞给你。

属性注入 = 练功后发放补充秘籍

对象已经创建好了
→ 门主根据需要给你补发更多秘籍(通过 public 属性)。

方法注入 = 参加某次大会才获得秘籍

某个关键方法被调用时
→ 门主把临时需要的秘籍交给你使用。

  1. 属性注入(Property Injection)

属性注入指:
DI 容器在对象创建后,会检查是否有可注入的 属性,然后自动填充。

特征:

  • 要求属性 public
  • 必须可写:set;
  • 通常要加特性(如 [Inject]

示例:属性注入

public class UserService
{
    [Inject]
    public ILogger Logger { get; set; }   // 容器会注入

    public void DoSomething()
    {
        Logger.Log("UserService working...");
    }
}

容器内部执行逻辑大概是:

  1. 先用构造函数创建对象:
    var obj = new UserService();
  2. 反射查找带 [Inject] 的属性
  3. 创建 ILogger 实例
  4. obj.Logger = loggerInstance

哪些容器支持属性注入?

容器 属性注入
ASP.NET Core 默认容器不支持
Autofac 支持
Unity 支持
Dryloc(Prism) 支持
Ninject 支持

WPF 项目 90% 使用 DryIoc(Prism) → 是支持属性注入的。

  1. 方法注入(Method Injection)

方法注入指:
调用某个方法时,容器会自动把参数的实例注入进去。

相当于:

“某场关键战斗时,门主在你进场前,把需要的武器塞给你。”

示例:方法注入

public class OrderService
{
    [Inject]
    public void Init(ILogger logger, ICache cache)
    {
        logger.Log("Init OrderService");
        this._cache = cache;
    }
}

容器逻辑:

  1. 对象创建完后
  2. 找到所有 [Inject] 方法
  3. 分析参数类型
  4. 调用:
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 时:

  1. 构造函数注入(如果有)
  2. 属性注入 UserService
  3. 方法注入 Init(logger)

总结

注入方式武侠含义:

  • 构造函数注入:入门时必学的基础武功
  • 属性注入:后来补给你的额外秘籍
  • 方法注入:上阵前临时发的特定武器

三者各有用途,但构造函数注入才是正门武学。

属性/方法注入是辅助手段,WPF 中 ViewModel 常用属性注入。