诺禾、.net core下运用事情总线

.net core下运用事情总线

  随着微效劳的火热,DDD(范畴驱动设计方式)思想风起云涌,冲击着整个软件生态系统。其中,事情总线那是必需知道的了,于是我便抱着一个学习DDD的心态搭建了一个博客网站,目前该网站正在树立阶段,后续会不时完善,这里我只是讲一下我里面所用到的事情总线。
  事情总线,我的理解就是发布订阅方式,这里有一篇文章写的比较好,我就是按着这个文章来完成的事情总线:事情总线知几。我之前按照他的文章别离自己写的,但是今天又看了下自己写的,发现好多都生疏了,所以觉得有必要来回想下,这里只是我个人的理解,如有不对请指出。

 事情总线就肯定要有事情源,这里我定义一个Command事情源:   

1
2
3
4
5
6
7
///
/// 范畴命令基类(此处文章里我称之为事情源)
///
public class Command
{

}
 然后我根据事情源来定义一个事情源处置的接口和它的完成类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
///
/// 创建用户范畴命令(创建事情源)
///
public class CreateUserCommand: Command
{
public CreateUserCommand(User user)
{
User = user;
}
public User User { get; private set; }

}
///
/// 用户命令处置程序(处置事情源)
///
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("该账号已存在"));
        return;
    }
    _userRepository.Insert(command.User);
}

}
此处我觉得曾经完成了关于事情源的功用,那么我们就来思索根据这个事情源来处置发布订阅的关系。

 就那注册用户功用来说,前面曾经将注册用户的事情源曾经写好了,那么发布订阅怎样处置呢?首先,我们应该清楚一个逻辑,那就是页面生成用户信息,后端获取信息生成UserModel,然后我们根据UserModel转为我们需求的CreateUserCommand,然后我们ICommandHandler根据CreateUserCommand来调用Handler,这是一个简单的调用逻辑。那么IcommandHnadler怎样知道调用哪一个Handler呢?那就是我将事情源和事情源处置类存入集合里面,这样我以后就会根据Command来获取到我的ICommandHandler了,又由于.net core遵照依赖注入准绳,所以我需求往容器了注入ICommander和他的完成类,就是UserCommandhandler,这个时分可以说是曾经将事情源都注册到了内存里了,以下是我的相关代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
///
/// 暂时存储类型数组
///
private static Type[] serviceTypes = Assembly.Load(“Blog.Domain”).GetTypes();

private static ConcurrentDictionary<Type, IList> handlerMapping = new ConcurrentDictionary<Type, IList>();

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

///
/// 注册事情总线(事情源)
///
/// ICommandler
/// CreateUserCommand
///
public static void AddEventBus<TImplementation, TService>(this IServiceCollection serviceDescriptors)
{
Type handler = typeof(TImplementation);
Type serviceType = serviceTypes.FirstOrDefault(s => handler.IsAssignableFrom(s));//获得接口的完成类
if (serviceType == null)
throw new ArgumentNullException(string.Format(“类型{0}未找到完成类”, handler.FullName));
serviceDescriptors.AddTransient(handler, serviceType);//.net core自带的IOC容器
GetOrAddHandlerMapping(typeof(TService)).Add(handler);//将事情源和事情源处置程序注册到内存里,可以说生成了一个订阅列表
}
   接下来我们再看发布与订阅,我要先定义一个发布订阅的中间件,

1
2
3
4
5
6
7
8
9
10
11
12
///
/// 中间件
///
public interface IEventBus
{
///
/// 发布
///
///
///
void Publish(TCommand command) where TCommand : Command;
}
  然后还有它的完成类,处置逻辑就是根据UserCommandHandler去ConcurrentDictionary里找到它的对应的ICommandHandler,然后在从IOC容器找到ICommandHandler的完成类,然后执行里面的方法,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public sealed class EventBus : IEventBus
{
private IServiceProvider _serviceProvider;
public EventBus(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
///
/// 发布事情
///
///
///
public void Publish(TCommand command) where TCommand : Command
{
IList types=typeof(TCommand).GetOrAddHandlerMapping();
if (types == null || types.Count == 0)
throw new ServiceException(“事情总线未注册:” + typeof(TCommand).Name);
foreach (var type in types)//从订阅列表里寻觅
{
object obj = _serviceProvider.GetService(type);
if(type.IsAssignableFrom(obj.GetType()))
{
ICommandHandler handler = obj as ICommandHandler;
if (handler != null)
handler.Handler(command);//
}
}
}
}
  这个时分可以说曾经完成了发布订阅,程序生成CreateUserCommand,这里我的理解为就是发布,调用Publish方法,这里我觉得就是订阅,然后最后执行Handler完成业务逻辑:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class UserService : IUserService
{
private readonly IUserRepository _userRepository;
private readonly IEventBus _eventBus;
///
/// 根据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));//创建事情源
_eventBus.Publish(command);//发布命令
}
}
还有就是最后的IServiceCollection注入了:

1
2
3
4
5
6
7
8
9
10
11
///
/// 效劳集合
///
///
public static void AddServices(this IServiceCollection services)
{
services.AddTransient<IUserRepository, UserRepository>();
services.AddTransient<IUserService, UserService>();
services.AddEventBus<ICommandHandler, CreateUserCommand>();
services.AddTransient<IEventBus,EventBus>()
services.DisposeServiceTypes();
}
  以上就是我对事情总线的细致应用,希望有大佬能指出我这菜鸟的缺乏指出!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值