如何设计从运行时配置加载对象的处理器
How to design a processor that loads objects from a runtime configuration
我正在实施一个调度程序。作为其核心逻辑的一部分,它处理自定义对象 Schedule。基本上它会遍历一系列计划并尝试处理它。问题是创建 Schedule 的人需要使用 ISchedule 接口将其注册到容器中。然后我的调度程序从容器中提取所有 ISchedule 引用。到目前为止,这是可行的,但它不具备加载时间表 运行 时间的灵活性。我可以采用什么样的设计和实现来实现一个可以加载那些 Schedules 运行 时间的 Scheduler。我正在提供一些示例代码。
我想到的事情是让开发人员编写一个 json 调度表示并将其放入配置中或实现一个 returns 该配置到调度程序的端点。但是我可以避免这种情况吗?我希望调度程序完全对抗开发人员代码。
您可以使用工厂注册有关时间表的信息类。并通过Id查找调度来动态改变调用间隔。
您在容器中注册: 和
public interface ISchedule
{
public string Id { get; set; }
public TimeSpan Interval { get; set; }
public DateTime? LastExecution { get; set; }
public bool CanStart { get; }
void Start();
void Stop();
}
public sealed class Schedule : ISchedule
{
public string Id { get; set; }
public TimeSpan Interval { get; set; }
public DateTime? LastExecution { get; set; }
public bool CanStart {
get
{
lock (_sync)
{
return !LastExecution.HasValue || LastExecution.Value.Add(Interval) >= DateTime.UtcNow;
}
}
}
private readonly object _sync = new object();
public void Start()
{
lock (_sync)
{
if (!LastExecution.HasValue || LastExecution.Value.Add(Interval) >= DateTime.UtcNow)
{
// DO WORK
LastExecution = DateTime.UtcNow;
}
}
}
public void Stop()
{
throw new NotImplementedException();
}
}
public interface IScheduleFactory
{
ISchedule Create();
}
public sealed class ScheduleFactory: IScheduleFactory
{
private readonly IScheduleManager _manager;
public ScheduleFactory(IScheduleManager manager)
{
_manager = manager;
}
public ISchedule Create()
{
var schedule = new Schedule();
_manager.Register(schedule);
return schedule;
}
}
public interface IScheduleManager
{
void Register(ISchedule schedule);
ISchedule Get(string id);
void Start();
void Stop();
}
public sealed class ScheduleManager : IScheduleManager
{
private readonly Dictionary<string,ISchedule> _items = new Dictionary<string, ISchedule>();
private readonly object _sync = new object();
public void Register(ISchedule schedule)
{
lock (_sync)
{
if (_items.ContainsKey(schedule.Id))
_items.Add(schedule.Id, schedule);
}
}
public ISchedule Get(string id)
{
lock (_sync)
{
if (_items.ContainsKey(id))
return _items[id];
}
return null;
}
private bool _isStart;
public void Start()
{
_isStart = true;
while (_isStart)
{
ISchedule[] array = null;
lock (_sync)
{
array = _items.Values.ToArray();
}
foreach (var schedule in array)
{
if (schedule.CanStart)
Task.Factory.StartNew(()=>schedule.Start());
}
}
}
public void Stop()
{
_isStart = false;
}
}
我正在实施一个调度程序。作为其核心逻辑的一部分,它处理自定义对象 Schedule。基本上它会遍历一系列计划并尝试处理它。问题是创建 Schedule 的人需要使用 ISchedule 接口将其注册到容器中。然后我的调度程序从容器中提取所有 ISchedule 引用。到目前为止,这是可行的,但它不具备加载时间表 运行 时间的灵活性。我可以采用什么样的设计和实现来实现一个可以加载那些 Schedules 运行 时间的 Scheduler。我正在提供一些示例代码。
我想到的事情是让开发人员编写一个 json 调度表示并将其放入配置中或实现一个 returns 该配置到调度程序的端点。但是我可以避免这种情况吗?我希望调度程序完全对抗开发人员代码。
您可以使用工厂注册有关时间表的信息类。并通过Id查找调度来动态改变调用间隔。
您在容器中注册:
public interface ISchedule
{
public string Id { get; set; }
public TimeSpan Interval { get; set; }
public DateTime? LastExecution { get; set; }
public bool CanStart { get; }
void Start();
void Stop();
}
public sealed class Schedule : ISchedule
{
public string Id { get; set; }
public TimeSpan Interval { get; set; }
public DateTime? LastExecution { get; set; }
public bool CanStart {
get
{
lock (_sync)
{
return !LastExecution.HasValue || LastExecution.Value.Add(Interval) >= DateTime.UtcNow;
}
}
}
private readonly object _sync = new object();
public void Start()
{
lock (_sync)
{
if (!LastExecution.HasValue || LastExecution.Value.Add(Interval) >= DateTime.UtcNow)
{
// DO WORK
LastExecution = DateTime.UtcNow;
}
}
}
public void Stop()
{
throw new NotImplementedException();
}
}
public interface IScheduleFactory
{
ISchedule Create();
}
public sealed class ScheduleFactory: IScheduleFactory
{
private readonly IScheduleManager _manager;
public ScheduleFactory(IScheduleManager manager)
{
_manager = manager;
}
public ISchedule Create()
{
var schedule = new Schedule();
_manager.Register(schedule);
return schedule;
}
}
public interface IScheduleManager
{
void Register(ISchedule schedule);
ISchedule Get(string id);
void Start();
void Stop();
}
public sealed class ScheduleManager : IScheduleManager
{
private readonly Dictionary<string,ISchedule> _items = new Dictionary<string, ISchedule>();
private readonly object _sync = new object();
public void Register(ISchedule schedule)
{
lock (_sync)
{
if (_items.ContainsKey(schedule.Id))
_items.Add(schedule.Id, schedule);
}
}
public ISchedule Get(string id)
{
lock (_sync)
{
if (_items.ContainsKey(id))
return _items[id];
}
return null;
}
private bool _isStart;
public void Start()
{
_isStart = true;
while (_isStart)
{
ISchedule[] array = null;
lock (_sync)
{
array = _items.Values.ToArray();
}
foreach (var schedule in array)
{
if (schedule.CanStart)
Task.Factory.StartNew(()=>schedule.Start());
}
}
}
public void Stop()
{
_isStart = false;
}
}