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

C# 如何设计从运行时配置加载对象的处理器,c#,architecture,scheduled-tasks,system,software-design,C#,Architecture,Scheduled Tasks,System,Software Design,我正在实现一个调度器。作为其核心逻辑的一部分,它处理一个自定义对象时间表。基本上,它会迭代一系列计划,并尝试对其进行处理。问题是谁创建了一个计划需要使用isSchedule接口向容器注册它。然后,我的调度程序从容器中提取所有isSchedule引用。到目前为止,这是可行的,但它没有加载时间表运行时的灵活性。我可以采用什么设计和实现来实现一个调度器,该调度器可以在运行时加载这些计划。我给出了一些示例代码 我想到的是让开发人员编写计划的json表示,并将其放在配置中,或者实现将该配置返回给调度程序的

我正在实现一个调度器。作为其核心逻辑的一部分,它处理一个自定义对象时间表。基本上,它会迭代一系列计划,并尝试对其进行处理。问题是谁创建了一个计划需要使用isSchedule接口向容器注册它。然后,我的调度程序从容器中提取所有isSchedule引用。到目前为止,这是可行的,但它没有加载时间表运行时的灵活性。我可以采用什么设计和实现来实现一个调度器,该调度器可以在运行时加载这些计划。我给出了一些示例代码


我想到的是让开发人员编写计划的json表示,并将其放在配置中,或者实现将该配置返回给调度程序的端点。但我能避免这种情况吗?我希望调度器能够完全支持开发人员代码。

您可以使用工厂注册有关调度类的信息。并通过Id查找调度来动态更改呼叫间隔。 您在容器中注册:和

公共接口已计划
{
公共字符串Id{get;set;}
公共时间间隔{get;set;}
公共日期时间?LastExecution{get;set;}
公共bool可以启动{get;}
void Start();
无效停止();
}
公开密封课程表:ISchedule
{
公共字符串Id{get;set;}
公共时间间隔{get;set;}
公共日期时间?LastExecution{get;set;}
公共图书馆可以启动{
得到
{
锁定(同步)
{
return!LastExecution.HasValue | | LastExecution.Value.Add(Interval)>=DateTime.UtcNow;
}
}
}
私有只读对象_sync=新对象();
公开作废开始()
{
锁定(同步)
{
如果(!LastExecution.HasValue | | LastExecution.Value.Add(Interval)>=DateTime.UtcNow)
{
//工作
LastExecution=DateTime.UtcNow;
}
}
}
公共停车场()
{
抛出新的NotImplementedException();
}
}
公共接口是调度属性
{
ISchedule Create();
}
公共密封类ScheduleFactory:isScheduleFactory
{
专用只读isScheduleManager\u管理器;
公共调度工厂(ISScheduleManager管理器)
{
_经理=经理;
}
public ISchedule Create()
{
var计划=新计划();
_经理。登记表(附表);
返回时间表;
}
}
公共接口ISScheduleManager
{
无效登记册(计划表);
ISchedule-Get(字符串id);
void Start();
无效停止();
}
公共密封类ScheduleManager:isScheduleManager
{
专用只读词典_items=new Dictionary();
私有只读对象_sync=新对象();
公共无效登记册(ISchedule附表)
{
锁定(同步)
{
如果(_items.ContainsKey(附表Id))
_添加项目(附表Id、附表);
}
}
公共ISSchedule获取(字符串id)
{
锁定(同步)
{
如果(_items.ContainsKey(id))
返回_项目[id];
}
返回null;
}
私人布卢伊斯塔特;
公开作废开始()
{
_isStart=true;
while(_isStart)
{
isSchedule[]数组=null;
锁定(同步)
{
数组=_items.Values.ToArray();
}
foreach(数组中的var调度)
{
if(schedule.CanStart)
Task.Factory.StartNew(()=>schedule.Start());
}
}
}
公共停车场()
{
_isStart=false;
}
}

我应该为开发人员提供什么基础设施来注册这些类。当前,容器在调度程序的同一实例中运行,如果我不断轮询,它每次都将获得相同的值。您可以将Remove方法添加到IsScheduleManager。开发人员需要添加新的计划并完成此操作,而我正在运行的实例需要获取新的计划。将计划存储在数据库存储中是否可行?开发人员可以使用schedule get(字符串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;
    }
}