【发布时间】:2017-05-21 06:01:43
【问题描述】:
我一直在考虑在我的网络应用中实现事件模型。
我需要实现的方法是:
- 从数据库中获取数据;
- 将其传递给 Grab 方法并收集数据;
- 将结果转换为适合我的数据并构建电子邮件、日志消息列表;
- 如果需要,通过电子邮件服务通知用户; (之后我们需要更改通知用户的 DB 中的 bool 标志)
- 将所有抓取日志写入某个存储;
- 将抓取的数据添加到 DB。
根据this 的回答,我决定使用上述示例。但是我已经积累了如何连接事件和传递我需要处理的数据。我有一个班级想从互联网上获取一些信息:
public interface IScheduleService
{
void ParseWebData(int userId);
}
public class ScheduleService : IScheduleService
{
IQueryHandler<ProductGrabbedInfoByUserQuery, IEnumerable<ProductGrabbedInfo>> GrabberQuery;
IEventPublisher publisher;
List<string> logMessages = new List<string>();
List<string> emailMessages = new List<string>();
public ScheduleService(IQueryHandler<ProductGrabbedInfoByUserQuery, IEnumerable<ProductGrabbedInfo>> GrabberQuery,
IEventPublisher publisher)
{
this.GrabberQuery = GrabberQuery;
this.publisher = publisher;
}
public void ParseWebData(int userId)
{
// получаем данные из БД
var qry = new ProductGrabbedInfoByUserQuery { UserId = 1 }; // пока что один юзер
var data = GrabberQuery.Handle(qry).ToList();
if (data.Any())
{
// собираем информацию
GrabberEngine ge = new GrabberEngine(BrowserType.Mozilla);
ge.Grab(data);
// преобразовываем в наш вид с собиранием логирования и ошибок
var converted = ConvertFromGrabbedInfo(data);
// HERE I THINK WE SHOULD CALL publisher.Publish(new GrabbingCompletedEvent{...}) to execute 3 points below:
// 1. Send email message using List<string> emailMessages info
// 2. Log messages using List<string> logMessages info
// 3. add collected data to DB
}
}
}
如果我们需要让事件数据最小化,那么我们需要存储一些小的值:
public class GrabbingCompletedEvent : IDomainEvent
{
public readonly string JobId;
public readonly int UserId;
public GrabbingCompletedEvent(string JobId, int UserId)
{
this.JobId = JobId;
this.UserId = UserId;
}
}
好的,那么我认为我们需要创建事件处理程序:
public class NotifyEmailGrabbingCompletedEventHandler : IEventHandler<GrabbingCompletedEvent>
{
private IEmailService emailService;
private readonly ILogger logger;
private IEnumerable<string> messages;
private IQueryHandler<GetByPrimaryKeyQuery<User>, User> UserQuery;
public NotifyEmailGrabbingCompletedEventHandler(IEmailService emailService,
ILogger logger,
IEnumerable<string> messages,
IQueryHandler<GetByPrimaryKeyQuery<User>, User> UserQuery)
{
this.emailService = emailService;
this.logger = logger;
this.messages = messages;
this.UserQuery = UserQuery;
}
public void Handle(GrabbingCompletedEvent e)
{
var user = GetUserInfo(e.UserId);
emailService.Send(user.Email, string.Join(Environment.NewLine, messages));
emailService.SetDelivered(true);
}
private User GetUserInfo(int userId)
{
var cmd = new GetByPrimaryKeyQuery<User> { PK = userId };
return UserQuery.Handle(cmd);
}
}
public class LogGrabbingCompletedEventHandler : IEventHandler<GrabbingCompletedEvent>
{
private readonly ILogger logger;
private IEnumerable<string> messages;
public LogGrabbingCompletedEventHandler(ILogger logger, IEnumerable<string> messages)
{
this.logger = logger;
this.messages = messages;
}
public void Handle(GrabbingCompletedEvent e)
{
foreach (var message in messages)
{
this.logger.Log(message);
}
}
}
我的问题是如何将记录器实例、消息列表和查询处理程序传递给当前处理程序?我在事件处理程序构造函数中传递这些参数是否正确?我想到的第一个变体是将这些数据作为属性添加到事件类中,但这似乎是一个错误的决定。能否请您解释一下哪种设计方法更适合这种情况。
【问题讨论】:
标签: c# design-patterns simple-injector