构造依赖注入下,如何从被调用类回调至调用类存储数据?
如何在依赖注入场景下从服务类更新主类的静态列表?
千万别在PeopleService里实例化Analyzer!这会把两个类死死绑定在一起,彻底违背依赖注入“解耦”的核心设计初衷,后续维护、扩展都会变得异常麻烦,甚至可能引发生命周期管理的问题。下面给你几个更规范的实现方式,按推荐程度排序:
1. 返回包含业务结果+附加信息的复合对象(最推荐)
这种方式最直观,也符合“方法返回其执行产生的全部相关信息”的设计原则。你可以创建一个专门的DTO类,同时封装People列表和缺失项:
// 新建复合结果类,用来封装业务结果和附加信息 public class PeopleForEventResult { public IList<People> People { get; set; } = new List<People>(); public IList<string> MissingMappingItems { get; set; } = new List<string>(); }
接着修改PeopleService的方法,返回这个复合对象:
public class PeopleService : IPeopleService { public PeopleForEventResult GetPeopleForEvent(string category, DateTime date) { var result = new PeopleForEventResult(); var ppl = new List<People>(); if(/* 你的原有判断条件 */) { // 原有逻辑填充ppl列表 result.People = ppl; } else { // 将需要记录的缺失项添加到结果对象的对应列表中 result.MissingMappingItems.Add("这里是缺失的映射项内容"); } return result; } }
最后在Analyzer中调用并处理结果:
public class Analyzer { private static readonly List<string> MissingItemsInMapping = new List<string>(); public IList<string> MissingItemsInMappingsList => MissingItemsInMapping; private readonly IPeopleService _peopleService; public Analyzer(IPeopleService peopleService) { _peopleService = peopleService; } public void YourCallingMethod(string category, DateTime date) { var result = _peopleService.GetPeopleForEvent(category, date); var people = result.People; // 将缺失项合并到Analyzer的静态列表中 // 加lock是为了线程安全,如果你的场景是单线程可以去掉 lock (MissingItemsInMapping) { MissingItemsInMapping.AddRange(result.MissingMappingItems); } } }
2. 通过回调委托传递逻辑
如果不想新建额外的类,可以在调用服务方法时传入一个回调委托,让PeopleService直接调用这个委托来添加缺失项:
修改PeopleService的方法签名:
public class PeopleService : IPeopleService { public IList<People> GetPeopleForEvent(string category, DateTime date, Action<string> addMissingItemCallback) { var ppl = new List<People>(); if(/* 你的原有判断条件 */) { // 原有逻辑填充ppl列表 return ppl; } else { // 直接调用回调委托,把缺失项传递给Analyzer处理 addMissingItemCallback("这里是缺失的映射项内容"); return new List<People>(); } } }
在Analyzer中调用时传入回调:
public void YourCallingMethod(string category, DateTime date) { var people = _peopleService.GetPeopleForEvent(category, date, item => { lock (MissingItemsInMapping) { MissingItemsInMapping.Add(item); } }); }
3. 使用事件通知(适合跨组件松散耦合场景)
如果PeopleService和Analyzer需要更低的耦合度,可以采用事件通知的方式:
首先在PeopleService中定义事件:
public class PeopleService : IPeopleService { // 定义事件,当发现缺失映射项时触发 public event EventHandler<string> MissingMappingItemFound; public IList<People> GetPeopleForEvent(string category, DateTime date) { var ppl = new List<People>(); if(/* 你的原有判断条件 */) { // 原有逻辑填充ppl列表 return ppl; } else { var missingItem = "这里是缺失的映射项内容"; // 触发事件,通知订阅者(比如Analyzer) MissingMappingItemFound?.Invoke(this, missingItem); return new List<People>(); } } }
然后在Analyzer的构造函数中订阅事件:
public Analyzer(IPeopleService peopleService) { _peopleService = peopleService; // 订阅PeopleService的事件 if (_peopleService is PeopleService concreteService) { concreteService.MissingMappingItemFound += (sender, item) => { lock (MissingItemsInMapping) { MissingItemsInMapping.Add(item); } }; } }
注意:这种方式需要IPeopleService暴露事件,或者向下转型到具体实现,如果你严格遵循面向接口编程,可能需要调整IPeopleService的定义,把事件加入接口中。
内容的提问来源于stack exchange,提问作者sm101
相关产品推荐
相关产品推荐

