我有一个系统,它从根本上用于解决异常并输出CSV 按需,详细说明每个已解决的项目。每天都会有新的例外情况需要处理。我的控制器中有一个POST
方法:
[HttpPost]
private ActionResult Resolve(ExceptionViewModel modifiedExceptionViewModel, string currentFilter)
{
// resolve database records...
return RedirectToAction("Index", "Exceptions");
}
我有一个新的要求,但是,用户希望系统识别最后一个未完成的时间,然后自动将CSV输出到文件共享,而不是必须手动执行此操作。
我首先创建了一个检查这是否是最后一个异常的方法,并调用了这个WasLastException();
我知道我可以将它包装在IF语句中并且在真正的调用中调用我调用的方法{{1} 1}}但在此之前,我想我会第一次尝试代表/事件,这导致我得到了类似的结果,但也提出了一些问题。
我的应用程序的一些背景
这是一个使用Unity DI的实体框架代码第一个MVC Web应用程序,我已将所有存储库调用包装在我的核心层的ProcessDataService类中,该类具有正在向Unity注册的接口IProcessDataService。
这就是我尝试添加活动的方式:
Controller的构造函数
OutputMasterFileCsv();
输出服务
public ExceptionsController(IProcessDataService service)
{
_service = service; //publisher
//event for delegate
OutputService outputService = new OutputService(_service); //subscriber
_service.LastException += outputService.OnLastException;
}
流程数据服务
public void OnLastException(object source, EventArgs e)
{
// output the CSV
}
控制器中的新解析方法
public delegate void LastExceptionEventHandler(object source, EventArgs args);
public class ProcessDataService : IProcessDataService
{
private readonly IExceptionRepository _exceptionRepository;
public ProcessDataService(IExceptionRepository evpRepo)
{
_exceptionRepository = evpRepo;
}
public event LastExceptionEventHandler LastException;
public void OnLastException()
{
if (LastException != null)
LastException(this, EventArgs.Empty);
}
}
这一切都运作良好,但是我觉得我不是在这里以某种方式在正确的位置使用分离和事件,而不是调用上面的[HttpPost]
private ActionResult Resolve(ExceptionViewModel modifiedExceptionViewModel, string currentFilter)
{
// resolve database records...
if(_service.WasLastException())
{
//raise the event
_service.OnLastException();
}
return RedirectToAction("Index", "Exceptions");
}
并利用事件,为什么我不能简单地致电已OnLastException()
班级的_service.OutputMasterFileCsv();
?
我认为这与松散耦合有关,但我并不完全明白这实际上有什么好处,或者我完全不同意这一切......?
我想在我有机会的时候我会先放弃它,并希望能够学到新的东西。如果任何有更多经验的人可以介入并提供一些指导,我将非常感激,因为我现在有点失落。
答案 0 :(得分:2)
正如你正确指出的那样,以这种方式使用事件没有多大意义:
if(_service.WasLastException())
{
//raise the event
_service.OnLastException();
}
您可以通过让IProcessDataService
公开ResolveException
操作,并将解析逻辑从控制器移动到服务来解决此问题:
[HttpPost]
private ActionResult Resolve(ExceptionViewModel modifiedExceptionViewModel, string currentFilter)
{
// make needed preparations...
_service.ResolveException(...prepared parameters...);
return RedirectToAction("Index", "Exceptions");
}
然后,在ProcessDataService.ResolveException
方法检查中
如果您当前正在处理最后一个异常,请举起LastException
事件。
public class ProcessDataService : IProcessDataService
{
//...
public ResolveException(...prepared parameters...) {
// resolve an exception and set lastException
if(lastException) {
this.OnLastException();
}
}
// notice the private modifier
private void OnLastException()
{
if (LastException != null)
LastException(this, EventArgs.Empty);
}
}
这样,数据处理服务只会在处理完最后一个异常时通知外部世界。当发生这种情况时,该服务不知道是否有人关心或做某事。控制器知道甚至更少。只有输出服务包含最后例外的处理逻辑。
话虽如此,事件的真正力量在于可以有许多订户,每个订户执行自己的任务而不了解其他订户。因此,您可以添加另一个事件处理程序来说明,向主管发送一封电子邮件,说明当天的所有例外情况都已解决。
重要的是,在这种情况下,您不需要修改控制器或其他服务来解释这个新引入的电子邮件发送功能。
答案 1 :(得分:0)
您已将控制器与存储中的服务和服务分离。那样就好。但我并不真正理解ProcessDataService中事件LastException的含义。这已经被接口IProcessDataService解耦,为什么要使用event?
另一个想法我不明白最后一个例外是什么?
如果要将outputService与ProcessDataService分离,可以这样做:
public ProcessDataService(IExceptionRepository evpRepo, IOutputService outputService)
{
_exceptionRepository = evpRepo;
_outputService = _outputService;
}
public void ProcessLastException()
{
_outputService.Command() //or whatever suitable name you for your method
}
在控制器中:
if(_service.WasLastException())
{
//call service
_service.ProcessLastException();
}
或者甚至更简单地添加一些方法来处理IProcessDataService的最后一个异常。
有more ways how to inject dependency。您已将依赖项注入构造函数,这就是为什么,您不需要事件进行解耦。