• C#中的事件聚合器实现方法


    概述:_对象之间的关系_是使代码库难以理解和难以维护的原因。为了更好地理解它,我们求助于马丁·福勒(Martin Fowler):事件聚合器是间接的简单元素。在最简单的形式中,您可以让它注册到您感兴趣的所有源对象,并让所有目标对象注册到事件聚合器。事件聚合器通过将源对象中的任何事件传播到目标对象来响应该事件。事件聚合器有很多好处。在本文中,我将展示事件聚合器如何使我们更容易扩展应用程序。给我一个理由!为了展示它如何使我们的代码更易于理解,请查看以下模型:public class User { public string Id { get; set; } public bool IsMarried_对象之间的关系_是使代码库难以理解和难以维护的原因。

    想了解更多游戏开发知识,可以扫描下方二维码,免费领取游戏开发4天训练营课程

    为了更好地理解它,我们求助于马丁·福勒(Martin Fowler):

    图片

    事件聚合器是间接的简单元素。在最简单的形式中,您可以让它注册到您感兴趣的所有源对象,并让所有目标对象注册到事件聚合器。事件聚合器通过将源对象中的任何事件传播到目标对象来响应该事件。

    事件聚合器有很多好处。在本文中,我将展示事件聚合器如何使我们更容易扩展应用程序。

    给我一个理由!

    为了展示它如何使我们的代码更易于理解,请查看以下模型:

    1. public class User {
    2. public string Id { get; set; }
    3. public bool IsMarried { get; set; }
    4. }
    5. public class Resume {
    6. public string Description { get; set; }
    7. public string UserId { get; set; }
    8. public bool IsUserMarried { get; set; }
    9. }
    10. public class Store {
    11. public string Title { get; set; }
    12. public string OwnerId { get; set; }
    13. public bool IsOwnerMarried { get; set; }
    14. }

    在这里,并将用户的当前婚姻状况存储在一个名为 的字段中。假设每个实体都是一个聚合根,因此每个实体都有自己的服务:ResumeStoreIsUserMarried

    1. public class ResumeService {
    2. private readonly ICollection<Resume> db = new List<Resume> {
    3. new Resume {
    4. Description = "My current resume",
    5. UserId = "1",
    6. IsUserMarried = false
    7. }
    8. };
    9. public void SetMaritalStatus(string userId, bool isMarried) {
    10. foreach (var resume in db.Where(a => a.UserId.Equals(userId))) {
    11. resume.IsUserMarried = isMarried;
    12. }
    13. }
    14. }
    15. public class StoreService {
    16. private readonly ICollection<Store> db = new List<Store> {
    17. new Store {
    18. Title = "Restaurant",
    19. OwnerId = "1",
    20. IsOwnerMarried = false
    21. }
    22. };
    23. public void SetMaritalStatus(string ownerId, bool isMarried) {
    24. foreach (var store in db.Where(a => a.OwnerId.Equals(ownerId))) {
    25. store.IsOwnerMarried = isMarried;
    26. }
    27. }
    28. }
    29. public class UserService {
    30. private readonly ICollection<User> db = new List<User> {
    31. new User {
    32. Id = "1",
    33. IsMarried = false
    34. }
    35. };
    36. private readonly ResumeService resumeService;
    37. private readonly StoreService storeService;
    38. public UserService(ResumeService resumeService,
    39. StoreService storeService) {
    40. this.resumeService = resumeService;
    41. this.storeService = storeService;
    42. }
    43. public void GotMarried(string userId) {
    44. var user = db.First(a => a.Id.Equals(userId));
    45. user.IsMarried = true;
    46. // propagate changes to other parts of the code
    47. resumeService.SetMaritalStatus(userId, true);
    48. storeService.SetMaritalStatus(userId, true);
    49. }
    50. }

    ResumeService并且两者都有一个更新用户婚姻状况的方法( )。正如你所看到的,对这两个服务都有依赖性,因为当一个用户结婚时,想要通知其他服务。此代码有效,但有两个缺点:StoreServiceSetMaritalStatusUserServiceUserService

    1-实际上不依赖或执行其操作!=>(假依赖关系)UserServiceResumeServiceStoreService

    2-每当我们添加存储用户婚姻状况的新实体时,我们必须记住更新!=>(难以扩展)GotMarriedUserService

    解决方案:事件聚合器

    与其引入依赖项(其他服务),不如调整定义一个事件:UserService

    1. public class MaritalStatusChanged : IEvent {
    2. public MaritalStatusChanged(string userId, bool isMarried) {
    3. UserId = userId;
    4. IsMarried = isMarried;
    5. }
    6. public string UserId { get; }
    7. public bool IsMarried { get; }
    8. }

    然后我们需要更新.首先删除依赖项,然后更新方法:UserServiceGotMarried

    1. public class UserService {
    2. private readonly ICollection<User> db = new List<User> {
    3. new User {
    4. Id = "1",
    5. IsMarried = false
    6. }
    7. };
    8. private readonly IEventEmitter eventEmitter
    9. public UserService(IEventEmitter eventEmitter) {
    10. this.eventEmitter = eventEmitter;
    11. }
    12. public void GotMarried(string userId) {
    13. var user = db.First(a => a.Id.Equals(userId));
    14. user.IsMarried = true;
    15. // propagate changes to other parts of the code
    16. eventEmitter.Publish(new MaritalStatusChanged(userId, true));
    17. }
    18. }

    所以现在,它只取决于事件发射器。活动发射器是我们的活动总线!它在整个域中发布事件。现在,如果想要了解此事件,我们只需创建一个处理程序。例如,这是一个添加到正文中的处理程序:ResumeService

    1. public class MaritalStatusChangedHandler :
    2. IEventHandler<MaritalStatusChanged> {
    3. private readonly ResumeService service;
    4. public MaritalStatusChangedHandler(ResumeService service) {
    5. this.service = service;
    6. }
    7. public Task Handle(MaritalStatusChanged ev) {
    8. service.SetMaritalStatus(ev.UserId, ev.IsMarried);
    9. return Task.CompletedTask;
    10. }
    11. }

    将它们粘在一起:

    1. // 1- create an event bus
    2. var bus = new DefaultEventBus();
    3. // 2- create services
    4. var userService = new UserService(bus);
    5. var resumeService = new ResumeService();
    6. var storeService = new StoreService();
    7. // 3- subscribe
    8. bus.Subscribe<MaritalStatusChanged, ResumeService.MaritalStatusChangedHandler>(
    9. new ResumeService.MaritalStatusChangedHandler(resumeService));
    10. bus.Subscribe<MaritalStatusChanged, StoreService.MaritalStatusChangedHandler>(
    11. new StoreService.MaritalStatusChangedHandler(storeService));
    12. // 4- someone got married
    13. userService.GotMarried("1");

    1- 这将创建事件总线。事件总线实现 IEventEmitter 和 IEventSink。 发布事件并允许您订阅事件。

    完整代码:

    1. using libc.eventbus.System;
    2. using libc.eventbus.Types;
    3. using Microsoft.VisualStudio.TestTools.UnitTesting;
    4. using System;
    5. using System.Collections.Generic;
    6. using System.Linq;
    7. using System.Threading.Tasks;
    8. namespace libc.eventbus.tests
    9. {
    10. [TestClass]
    11. public class Showcase2
    12. {
    13. [TestMethod]
    14. public void Showcase()
    15. {
    16. // 1- create an event bus
    17. var bus = new DefaultEventBus();
    18. // 2- create services
    19. var userService = new UserService(bus);
    20. var resumeService = new ResumeService();
    21. var storeService = new StoreService();
    22. // 3- subscribe
    23. bus.Subscribe<MaritalStatusChanged, ResumeService.MaritalStatusChangedHandler>(
    24. new ResumeService.MaritalStatusChangedHandler(resumeService));
    25. bus.Subscribe<MaritalStatusChanged, StoreService.MaritalStatusChangedHandler>(
    26. new StoreService.MaritalStatusChangedHandler(storeService));
    27. // 4- someone got married
    28. userService.GotMarried("1");
    29. }
    30. public class UserService
    31. {
    32. private readonly ICollection<User> _db = new List<User>
    33. {
    34. new User
    35. {
    36. Id = "1",
    37. IsMarried = false
    38. }
    39. };
    40. private readonly IEventEmitter _eventEmitter;
    41. public UserService(IEventEmitter eventEmitter)
    42. {
    43. _eventEmitter = eventEmitter;
    44. }
    45. public void GotMarried(string userId)
    46. {
    47. var user = _db.First(a => a.Id.Equals(userId));
    48. user.IsMarried = true;
    49. // propagate changes to other parts of the code
    50. _eventEmitter.Publish(new MaritalStatusChanged(userId, true));
    51. }
    52. }
    53. public class ResumeService
    54. {
    55. private readonly ICollection<Resume> _db = new List<Resume>
    56. {
    57. new Resume
    58. {
    59. Description = "My current resume",
    60. UserId = "1",
    61. IsUserMarried = false
    62. }
    63. };
    64. public void SetMaritalStatus(string userId, bool isMarried)
    65. {
    66. foreach (var resume in _db.Where(a => a.UserId.Equals(userId))) resume.IsUserMarried = isMarried;
    67. Console.WriteLine($"{userId} is {(isMarried ? "married" : "single")} now");
    68. }
    69. public class MaritalStatusChangedHandler : IEventHandler<MaritalStatusChanged>
    70. {
    71. private readonly ResumeService _service;
    72. public MaritalStatusChangedHandler(ResumeService service)
    73. {
    74. _service = service;
    75. }
    76. public Task Handle(MaritalStatusChanged ev)
    77. {
    78. _service.SetMaritalStatus(ev.UserId, ev.IsMarried);
    79. return Task.CompletedTask;
    80. }
    81. }
    82. }
    83. public class StoreService
    84. {
    85. private readonly ICollection<Store> _db = new List<Store>
    86. {
    87. new Store
    88. {
    89. Title = "Restaurant",
    90. OwnerId = "1",
    91. IsOwnerMarried = false
    92. }
    93. };
    94. public void SetMaritalStatus(string userId, bool isMarried)
    95. {
    96. foreach (var store in _db.Where(a => a.OwnerId.Equals(userId))) store.IsOwnerMarried = isMarried;
    97. Console.WriteLine($"{userId} is {(isMarried ? "married" : "single")} now");
    98. }
    99. public class MaritalStatusChangedHandler : IEventHandler<MaritalStatusChanged>
    100. {
    101. private readonly StoreService _service;
    102. public MaritalStatusChangedHandler(StoreService service)
    103. {
    104. _service = service;
    105. }
    106. public Task Handle(MaritalStatusChanged ev)
    107. {
    108. _service.SetMaritalStatus(ev.UserId, ev.IsMarried);
    109. return Task.CompletedTask;
    110. }
    111. }
    112. }
    113. public class MaritalStatusChanged : IEvent
    114. {
    115. public MaritalStatusChanged(string userId, bool isMarried)
    116. {
    117. UserId = userId;
    118. IsMarried = isMarried;
    119. }
    120. public string UserId { get; }
    121. public bool IsMarried { get; }
    122. }
    123. public class User
    124. {
    125. public string Id { get; set; }
    126. public bool IsMarried { get; set; }
    127. }
    128. public class Resume
    129. {
    130. public string Description { get; set; }
    131. public string UserId { get; set; }
    132. public bool IsUserMarried { get; set; }
    133. }
    134. public class Store
    135. {
    136. public string Title { get; set; }
    137. public string OwnerId { get; set; }
    138. public bool IsOwnerMarried { get; set; }
    139. }
    140. }
    141. }
  • 相关阅读:
    Llama3 中文通用 Agent 微调模型来啦!(附手把手微调实战教程)
    《使用Gin框架构建分布式应用》阅读笔记:p52-p76
    CentOS7.x部署GreenPlum6.x
    vue.js实例选项
    【MySQL】增删改查进阶
    高级开发要会高效Java
    面试2:通用能力
    [认知能力]电子信息类专业新生暑假可以先预习一些什么专业内容?
    springboot+zookeepr+dubbo的远程服务调用
    10.07hw
  • 原文地址:https://blog.csdn.net/2401_82584055/article/details/139274567