Using event bus in. Net core

Time:2021-1-20
 
     With the popularity of microservices, DDD (Domain Driven Design Pattern) ideas are surging, impacting the entire software ecosystem. Among them, the event bus must be known, so I built a blog website with a mind of learning DDD. At present, the website is in the construction stage, and it will continue to improve in the future. Here I just talk about the event bus I used in it.

Event bus, my understanding is publish subscribe mode, here is an article written better, I am according to this article to complete the event bus: event bus know how much. I used to write according to his articles combined with my own, but today I read what I wrote, and found that many of them are unfamiliar, so I think it is necessary to recall. Here is my personal understanding, if there is anything wrong, please point out.

Event bus must have an event source. Here I define a command event source
/// 
    ///Domain command base class (I call it event source here)
    /// 
    public  class Command
    {
        
    }

Then I define an interface for event source processing and its implementation class according to the event source

/// 
    ///Create user domain command (create event source)
    /// 
    public class CreateUserCommand: Command
    {
        public CreateUserCommand(User user)
        {
            User = user;
        }
        public User User { get; private set; }

    }
    /// 
    ///User command handler (handling event sources)
    /// 
    public class UserCommandHandler : ICommandHandler, 
    {
        private readonly IUserRepository _userRepository;
        private readonly IEventBus _eventBus;
        public UserCommandHandler(IUserRepository userRepository, IEventBus eventBus)
        {
            _userRepository = userRepository;
            _eventBus = eventBus;
        }

        public void Handler(CreateUserCommand command)
        {
            int count = _userRepository.SelectCountByAccount(command.User.Account);
            if (count > 0)
            {
                _ eventBus.RaiseEvent (New notifyvalidation ("the account already exists");
                return;
            }
            _userRepository.Insert(command.User);
        }
    }

Here, I think the function of event source has been completed. Let’s consider how to handle the relationship between publish and subscribe according to this event source.

As far as the registered user function is concerned, the event source of the registered user has been written, so what about publish subscribe? First of all, we should be clear about a logic, that is, the page generates user information, the back-end obtains the information to generate a user model, and then we convert the user model to the create user command we need, and then we icommandhandler calls the handler according to the create user command. This is a simple calling logic. So how does icommandhnadler know which handler to call? That is, I store the event source and event source processing class into the collection, so that I can get my icommandhandler according to the command in the future, and because. Net Core follows the principle of dependency injection, so I need to inject icommander and its implementation class, that is, usercommandhandler, into the container. At this time, I can say that the event source has been registered in memory. The following is my related code:

 
/// 
        ///Temporary storage type array
        /// 
        private static Type[] serviceTypes = Assembly.Load("Blog.Domain").GetTypes();
 
        private static ConcurrentDictionary> handlerMapping = new ConcurrentDictionary>();

        public static IList GetOrAddHandlerMapping(this Type eventType)
        {
           return handlerMapping.GetOrAdd(eventType,(Type type)=>new List());
        }

        /// 
        ///Register event bus (event source)
        /// 
        /// ICommandler
        /// CreateUserCommand
        /// 
        public static void AddEventBus(this IServiceCollection serviceDescriptors)
        {
            Type handler = typeof(TImplementation);
            Type serviceType =  serviceTypes.FirstOrDefault (s =>  handler.IsAssignableFrom (s) ); // get the implementation class of the interface
            if (serviceType == null)
                throw new ArgumentNullException( string.Format ("implementation class not found for type {0}"), handler.FullName ));
            serviceDescriptors.AddTransient (handler, ServiceType); //. Net core's own IOC container
            Getoraddhandlermapping (type of (tservice)). Add (handler); // register the event source and event source handler in memory to generate a subscription list
        }

Next, let’s look at publish and subscribe. I want to define a publish subscribe middleware,

/// 
    ///Middleware
    /// 
   public  interface  IEventBus
    {
        /// 
        ///Release
        /// 
        /// 
        /// 
        void Publish(TCommand command) where TCommand : Command;
     }

Then there is its implementation class. The processing logic is to find its corresponding icommandhandler in the concurrent dictionary according to the usercommandhandler, and then find the implementation class of icommandhandler from the IOC container, and then execute the methods in it, as follows:

public sealed class EventBus : IEventBus
    {
        private IServiceProvider _serviceProvider;
        public EventBus(IServiceProvider serviceProvider)
        {
            _serviceProvider = serviceProvider;
        }
        /// 
        ///Release event
        /// 
        /// 
        /// 
        public void Publish(TCommand command) where TCommand : Command
        {
            IList types=typeof(TCommand).GetOrAddHandlerMapping();
            if (types == null || types.Count == 0)
                Throw new serviceexception ("event bus not registered): + typeof (tcommand). Name];
            Foreach (VaR type in types) // search from subscription list
            {
                object obj = _serviceProvider.GetService(type);
                if(type.IsAssignableFrom(obj.GetType()))
                {
                    ICommandHandler handler = obj as ICommandHandler;
                    if (handler != null)
                        handler.Handler(command);//
                }
            }
        }
  }

At this time, it can be said that the publish / subscribe has been completed, and the program generates the createusercommand. My understanding here is to publish and call the publish method. Here I think it is to subscribe, and then execute the handler to complete the business logic

public class UserService : IUserService
    {
        private readonly IUserRepository _userRepository;
        private readonly IEventBus _eventBus;
        /// 
        ///Convert to entity based on usermodel
        /// 
        /// 
        /// 
        private User TransferModel(UserModel userModel)
        {
            return user;
        }
        public UserService(IUserRepository userRepository, IEventBus eventBus)
        {
            _userRepository = userRepository;
            _eventBus = eventBus;
        }
        public void Insert(UserModel userModel)
        {
            userModel.Password = EncrypUtil.MD5Encry(userModel.Password);
            Var command = new createusercommand (transfermodel (usermodel)); // create event source
            _ eventBus.Publish (command); // issue command
        }
}

Then there is the final iservicecollection injection:

/// 
        ///Service collection
        /// 
        /// 
        public static void AddServices(this IServiceCollection services)
        {
            services.AddTransient();
            services.AddTransient();
            services.AddEventBus, CreateUserCommand>();            services.AddTransient()
            services.DisposeServiceTypes();
        }

The above is my specific application of event bus, I hope that a boss can point out the shortcomings of my rookie!

        A good memory is not as good as a bad pen, so I used this tool in my website. The address of my personal website is: www.ttblog.site , the address of the source code is: https://github.com/Hansdas/BlogH.git , personal site is in the construction stage, many functions are not perfect, due to time reasons, so the progress is relatively slow, but I also go to improve every day when I get home,No matter how bad the food you cook, you have to finish itThe website that oneself do, not good-looking also should care attentively.