class ParserWorker where T : class { //поле с обобщенным типом IParser IParser parser; //поле, в котором хранятся настройки для парсера IParserSettings parserSettings; HtmlLoader loader; bool isActive; private HabraParser habraParser; private HabraSettings habraSettings; // пара публичных свойств для полей parser и parserSettings #region Properties public IParser Parser { get { return parser; } set { parser = value; } } public IParserSettings Settings { get { return parserSettings; } set { parserSettings = value; //создаем новый экземпляр с новыми настройками парсера loader = new HtmlLoader(value); } } //свойство, доступное лишь для чтения для контроля работы класса public bool IsActive { get { return IsActive; } } //#region позволяет указать блок кода, который можно разворачивать и сворачивать в редакторе кода Visual Studio. #endregion //пара событий //первое событие, возвращающее спарсенные за итерацию данные.В аргументах мы передаем ссылку на парсер, а затем public event Action OnNewData; //второе событие отвечает за информирование при завершении работы парсера public event Action OnCompleted; //конструктор, в котором принимается экземпляр, реализующий интерфейс IParser public ParserWorker(IParser parser) { //присваиваем значение аргумента полю this.parser = parser; } //конструктор,который кроме парсера принимает его настройки public ParserWorker(IParser parser, IParserSettings parserSettings) : this(parser)//чтобы не дублировать код, вызываем первый конструктор и передадим ему парсер {//записываем настройки парсера в поле this.parserSettings = parserSettings; } public ParserWorker(HabraParser habraParser, HabraSettings habraSettings) { this.habraParser = habraParser; this.habraSettings = habraSettings; } //добавляем два метода для запуска и остановки парсера - Start и Abort public void Start() {//в методе Start вызываем метод Worker (он будет асинхронным) isActive = true; Worker(); } public void Abort() { isActive = false; } //закрытый асинхронный метод Worker, контролирующий процесс парсинга private async void Worker() {//цикл от стартовой до конечной точки из наших настроек for (int i = parserSettings.StartPoint; i <= parserSettings.EndPoint; i++) {//делаем проверку на активность. Если был использован метод Abort, то выходим из метода if (!isActive) {//вызов метода OnCompleted в случае, если работа парсера была остановлена OnCompleted?.Invoke(this); return; } //С помощью HtmlLoadera получаем исходный код страницы с индексом из цикла var source = await loader.GetSourceByPageId(i); //создаем HtmlParser, доступный нам из AngleSharp var domParser = new HtmlParser(); //спарсим асинхронно наш исходный код и получим документ, с которым можно работать var document = await domParser.ParseAsync(source); //передаем нашему парсеру документ и получаем спарсенные данные в переменную result var result = parser.Parse(document); //вызов метода OnNewData, в который передается ссылка и результат OnNewData?.Invoke(this, result); } //вызов метода OnCompleted в случае, если работа парсера была закончена OnCompleted?.Invoke(this); isActive = false; } }