【发布时间】:2016-08-01 04:30:13
【问题描述】:
我有“处理程序”能够触发“经纪人”(一个做某事的对象 - 在这里不重要)。
处理程序正在监听不同类型的事件:
- TimeEvent:每 10 秒、10 分钟 (...)
- FileSystemEvent:一旦文件被复制/移动/删除
- DbEvent:将记录添加到数据库表时
- MailEvent:当我在 Office 365 邮箱中收到电子邮件时
每个处理程序必须有:
- 启动和停止方法(启动/停止捕获事件)
- 关联代理的实例
- 一种“触发”代理的方法(流程方法 + 特定参数集)。
每个处理程序都应该
- 引发特定事件时触发关联代理
我想从基本的 Handler 类触发代理,因此我集中了我的逻辑(触发事件、捕获异常、管理线程等)。但是,基本处理程序不知道如何调用代理(何时调用此函数,向 Process 方法发送什么参数)>> 只有专门的子处理程序知道如何执行此操作。
我发现的唯一方法是在基处理程序中实现一个接受 Action 参数的 Execute 方法...我不喜欢这种方法,因为它不是很直接(孩子需要调用基类,否则什么也不会发生)。我希望找到一个更好的设计来处理这个问题。另外我可以告诉你我的开发人员会告诉我他们不明白如何使用这个系统。
abstract class Handler : IHandler
{
public IBroker Broker { get; protected set; }
public event ProcessedEventHandler Processed;
protected void OnProcessed(ProcessExecutionResult result) => Processed?.Invoke(this, result);
public static IHandler Create(IBroker broker)
{
if (broker is ITimerTriggeredBroker)
return new TimeHandler((ITimerTriggeredBroker)broker);
return null;
}
protected Handler(IBroker broker)
{
if (broker == null) throw new ArgumentNullException(nameof(broker));
Broker = broker;
}
public abstract void Start();
public abstract void Stop();
protected void Execute(Action action)
{
var res = new ProcessExecutionResult();
try
{
action?.Invoke();
res.IsSuccess = true;
}
catch (Exception ex)
{
res.Exception = ex;
res.IsSuccess = false;
}
finally
{
OnProcessed(res);
}
}
}
TimeHandler(处理时间相关事件)
class TimeHandler : Handler
{
private readonly Timer _timer;
private readonly DateTime _start;
private readonly TimeSpan _frequency;
public TimeHandler(ITimerTriggeredBroker broker)
: base(broker)
{
_start = broker.Trigger.StartTime;
_frequency = broker.Trigger.Frequency;
_timer = new Timer(_ => Execute(broker.Process));
}
(...)
}
FileHandler(处理 FileSystem 相关事件)
class FileHandler : Handler
{
private readonly FileSystemWatcher _watcher = new FileSystemWatcher();
public FileHandler(IFileTriggeredBroker broker)
: base(broker)
{
if (!Directory.Exists(broker.Trigger.DirectoryPath))
throw new DirectoryNotFoundException("Unable to locate the supplied directory");
_watcher.Filter = broker.Trigger.Filter;
_watcher.Path = broker.Trigger.DirectoryPath;
_watcher.NotifyFilter = NotifyFilters.CreationTime | NotifyFilters.DirectoryName |
NotifyFilters.FileName;
_watcher.Created += (s, a) =>
{
if (IsCopied(a.FullPath)) Execute(() => broker.Process(a.FullPath));
};
}
【问题讨论】:
-
你打算如何注入
IHandler > Handler > TimedHandler? -
“只有专门的儿童处理程序知道如何做到这一点。”——听起来像是多态性/虚拟方法的工作。但无法确定,因为您提供了足够的细节来创建一个非常广泛的问题。代码片段没有提供足够的上下文,有很多方法可以解决这个含糊不清的问题。如果你得到一个好的答案,它只会在 cmets 中来回很多之后才会出现。否则,你只会得到很多随机猜测。请改进问题。从一个好的minimal reproducible example 开始,并准确地解释你的困扰。
标签: c# events design-patterns