惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Hacker News: Ask HN
Hacker News: Ask HN
月光博客
月光博客
Martin Fowler
Martin Fowler
人人都是产品经理
人人都是产品经理
有赞技术团队
有赞技术团队
Hugging Face - Blog
Hugging Face - Blog
T
Tailwind CSS Blog
爱范儿
爱范儿
博客园_首页
Last Week in AI
Last Week in AI
N
Netflix TechBlog - Medium
NISL@THU
NISL@THU
H
Help Net Security
A
Arctic Wolf
K
Kaspersky official blog
Y
Y Combinator Blog
G
GRAHAM CLULEY
T
Threatpost
I
Intezer
Attack and Defense Labs
Attack and Defense Labs
Jina AI
Jina AI
Recent Announcements
Recent Announcements
D
Docker
博客园 - 聂微东
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
www.infosecurity-magazine.com
www.infosecurity-magazine.com
GbyAI
GbyAI
The Hacker News
The Hacker News
C
Cyber Attacks, Cyber Crime and Cyber Security
Help Net Security
Help Net Security
Microsoft Azure Blog
Microsoft Azure Blog
G
Google Developers Blog
F
Fortinet All Blogs
S
Security Affairs
Security Archives - TechRepublic
Security Archives - TechRepublic
量子位
AWS News Blog
AWS News Blog
Google DeepMind News
Google DeepMind News
罗磊的独立博客
V
Vulnerabilities – Threatpost
阮一峰的网络日志
阮一峰的网络日志
T
Tor Project blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
H
Hacker News: Front Page
Security Latest
Security Latest
The Cloudflare Blog
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
M
MIT News - Artificial intelligence
B
Blog
云风的 BLOG
云风的 BLOG

博客园 - xiangji

开源完美模块组件化可扩展的Xml解析器Hand.ParseXml Roslyn语法的模式匹配之EasySyntax增加模式匹配支持 SourceGenerator之扑风捉影 开源项目PocoEmit.Mapper重构之扑风捉影 .NET源码生成器基于partial范式开发和nuget打包 SourceGenerator之partial范式及测试 .NET源码生成器之SyntaxTree踩坑 .NET源码生成器使用SyntaxTree生成代码及简化语法 DBShadow.net之化繁为简 DBShadow.net之性能优化的坎坷路 DBShadow横空出世,Dapper.net的天花板盖不住了 Aspire+.NET10+手搓线程池打造抓不死的云应用 鸡肋的TaskFactory是时候抛弃了 重构《手搓》TaskFactory带你更安全的起飞 异步"伪线程"重构《手搓》线程池,支持任务清退 《手搓》线程池优化的追求 《手搓》TaskFactory带你安全的起飞 《手搓》线程池 致敬1024,《手搓》轻量级EventBus PocoEmit遥遥领先于AutoMapper之打通充血模型的任督二脉 PocoEmit遥遥领先于AutoMapper之循环引用 微软.net表达式编译居然有bug? 如何使用PocoEmit.Mapper替代AutoMapper
DBShadow.net之依赖注入
xiangji · 2026-01-26 · via 博客园 - xiangji

一、充血模型

二、来个Case演示一下DBShadow注入

1. 充血模型代码

  • 为了方便修改AccountModify增加了方法ModifyAsync
  • 为了实现AccountModify方法注入了AccountModifyService
  • 这就是个典型充血模型
/// <summary>
/// 账户修改
/// </summary>
/// <param name="service"></param>
public class AccountModify(AccountModifyService<Account> service)
    : Account
{
    private readonly AccountModifyService<Account> _service = service;
    /// <summary>
    /// 账户修改
    /// </summary>
    /// <param name="token"></param>
    /// <returns></returns>
    public Task ModifyAsync(long amount, CancellationToken token = default)
    {
        Amount = amount;
        return _service.ModifyAsync(this, token);
    }
}

2. 服务初始化

  • mapper既支持预编译也支持依赖注入,两者必须用同一个mapper
  • AccountGetService是泛型服务,它可以支持普通模型也支持充血模型
  • _accountService获取普通模型对象
  • _accountService2获取充血模型对象
private static readonly IMapper _mapper = Mapper.Create(); 
private static readonly IShadowBuilder _builder = ShadowBuilder.CreateCache(_mapper, _engine, _dataSource);
private static readonly AccountTable _table = new();
private static readonly AccountModifyService<Account> _modifyService = new(_table, _builder);
private static readonly AccountGetService<long, Account> _accountService = new(_table, _builder);
private static readonly AccountGetService<long, AccountModify> _accountService2 = new(_table, _builder);

3. “注册服务”

  • UseDefault是PocoEmit一种简化的注入机制
  • PocoEmit处理属性和构造函数参数缺失映射规则时会从UseDefault的配置中查找
_mapper.UseDefault(_modifyService);

4. 依赖注入演示代码

  • _accountService2获取充血模型,余额为1000
  • 使用充血模型的方法ModifyAsync把余额修改为500
  • 使用_accountService获取普通模型对象,确认余额已经是500了
  • 充血模型和普通模型是使用相同类获取的,都成功了
  • 最重要的是AccountModify能正常工作,说明AccountModify的service注入成功
var accountModify = await _accountService2.GetAsync(1L);
Assert.NotNull(accountModify);
Assert.Equal(1000L, accountModify.Amount);
await accountModify.ModifyAsync(500L);
var account = await _accountService.GetAsync(1L);
Assert.NotNull(account);
Assert.Equal(1L, account.Id);
Assert.Equal(500L, account.Amount);

三、用IOC注入

  • PocoEmit支持IOC注入
  • DBShadow自然也继承了IOC注入功能
  • 下面Case演示一下IOC注入

1. IOC注册代码

  • 其中UseSingleton是告知PocoEmit从IOC容器获取服务用来注入
  • 详情查看文章PocoEmit遥遥领先于AutoMapper之打通充血模型的任督二脉
  • 另外服务都是注册成单例,这点与EF要区别开,基于EF的服务一般都需要注册为Scope
  • 因为DBShadow是线程安全的架构,对异步、多线程友好
  • 当然定义为非单例的也能正常运行
var mapper = Mapper.Default;
IShadowBuilder builder = ShadowBuilder.CreateCache(mapper, _engine, _dataSource);
var services = new ServiceCollection()
    .AddSingleton(mapper)
    .AddSingleton(builder)
    .AddSingleton<AccountTable>()
    .AddSingleton(typeof(AccountCreateService<>))
    .AddSingleton(typeof(AccountModifyService<>))
    .AddSingleton(typeof(AccountGetService<,>));
var serviceProvider = services.BuildServiceProvider();
mapper.UseSingleton(serviceProvider);

2. 演示代码

  • 执行代码与前面的Case基本一致
  • 说明DBShadow与PocoEmit完美对接上了
  • 也可以说DBShadow与IOC容器也完美对接上了
var accountService = serviceProvider.GetRequiredService<AccountGetService<long, Account>>();
var accountService2 = serviceProvider.GetRequiredService<AccountGetService<long, AccountModify>>();

var accountModify = await accountService2.GetAsync(1L);
Assert.NotNull(accountModify);
Assert.Equal(1000L, accountModify.Amount);
await accountModify.ModifyAsync(500L);
var account = await accountService.GetAsync(1L);
Assert.NotNull(account);
Assert.Equal(500L, account.Amount);

四、总结

  • DBShadow继承了PocoEmit的依赖注入功能
  • 充血模型是一种OOP的开发方式,可以增加代码可读性
  • DBShadow能有效简化充血模型的使用
  • DBShadow是线程安全的架构,适合异步、多线程、高并发和微服务的场景
  • 本文Case来源DBShadow项目的单元测试,可以查阅源码

源码托管地址: https://github.com/donetsoftwork/DBShadow.net ,欢迎大家直接查看源码。
gitee同步更新:https://gitee.com/donetsoftwork/DBShadow.net

如果大家喜欢请动动您发财的小手手帮忙点一下Star,谢谢!!!