如何设计从运行时配置加载对象的处理器

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;
    }
}