RPM*_*984 8 c# asp.net-mvc events design-patterns asp.net-mvc-3
我的ASP.NET MVC 3站点上都有这样的控制器代码:
[HttpPost]
public ActionResult Save(PostViewModel viewModel)
{
// VM -> Domain Mapping. Definetely belongs here. Happy with this.
var post = Mapper.Map<PostViewModel, Post>(viewModel);
// Saving. Again, fine. Controllers job to update model.
_postRepository.Save(post);
// No. Noooo..caching, thread spawning, something about a user?? Why....
Task.Factory.StartNew(() => {
_cache.RefreshSomeCache(post);
_cache2.RefreshSomeOtherCache(post2);
_userRepository.GiveUserPoints(post.User);
_someotherRepo.AuditThisHappened();
});
// This should be the 3rd line in this method.
return RedirectToAction("Index");
}
Run Code Online (Sandbox Code Playgroud)
基本上,我指的是线程块中的代码.所有事情都需要发生,但用户不需要等待它们(对于后台线程来说是好的,对吧?).
为了清楚起见,我在整个站点使用缓存(常规ASP.NET数据缓存),其中大部分都有"无过期"缓存策略,因此我在需要时手动逐出(如上所述).
用户部分基本上是为用户代表做某事(比如Stack).
让我们回顾一下:我们有缓存,用户信誉处理,审计,一体化.真的不属于一个地方吗.因此,当前代码的问题,以及试图找出如何移动它的问题.
我想重构这个的原因有以下几个原因:
我解决了1)将线程产生的代码包装到一个接口中,然后只是嘲笑/伪造它.
但我想做某种模式,我的代码看起来像这样:
[HttpPost]
public ActionResult Save(PostViewModel viewModel)
{
// Map.
var post = Mapper.Map<PostViewModel, Post>(viewModel);
// Save.
_postRepository.Save(post);
// Tell someone about this.
_eventManager.RaiseEvent(post);
// Redirect.
return RedirectToAction("Index");
}
Run Code Online (Sandbox Code Playgroud)
基本上,把责任放在"别的东西"上做出反应,而不是控制器.
我听说过有关任务,命令,事件等的内容,但还没有看到在ASP.NET MVC空间中实现的内容.
初步想法会告诉我创建某种"事件管理器".但后来我想,这是怎么回事?在域名?那么它如何处理与缓存的交互,这是一个基础设施问题.然后是线程,这也是一个基础设施问题.如果我想要做的是同步,而不是异步?是什么决定的?
我不想只是把所有这些逻辑都堆积在其他地方.理想情况下,它应该被重新考虑到可管理和有意义的组件,而不是转移责任,如果这是有道理的.
有什么建议?
第一个想法会告诉我创建某种“事件管理器”。但后来我想,这会去哪里呢?在域中?
这就是我解决问题的方法。我将事件管理器视为基础设施。但实际事件属于领域。
那么它如何处理与缓存的交互,这是一个基础设施问题。然后是线程,这也是一个基础设施问题。如果我想做的是同步而不是异步怎么办?是什么做出了这个决定?
异步很好,但使事务处理变得复杂。如果您使用 IoC 容器,您已经拥有明确定义的范围和可在事件传播期间使用的事务。
恕我直言,如果订阅者知道事件处理需要时间,则由订阅者来安排/线程其任务。
建议的解决方案:
使用 IoC 容器发布事件。我会让存储库发布事件(或者PostUpdated
取决于EntityUpdated
您想要对事件执行的操作)而不是控制器(以减少代码重复)。
我为 autofac 做了一个 IoC 实现,它允许您:
DomainEventDispatcher.Current.Dispatch(new EntityUpdated(post));
Run Code Online (Sandbox Code Playgroud)
订阅:
public class CacheService : IAutoSubscriberOf<EntityUpdated>
{
public void Handle(EntityUpdated domainEvent) {};
}
Run Code Online (Sandbox Code Playgroud)
https://github.com/sogeti-se/Sogeti.Pattern/wiki/Domain-events
典型用法
ServiceResolver.Assign(new yourResolver(yourContainer))
归档时间: |
|
查看次数: |
418 次 |
最近记录: |