У меня есть объект, который может занять от двух секунд до нескольких минут для инициализации. Причина заключается в том, что конструктор извлекает данные из веб-службы, которая может быть от нескольких килобайт до нескольких мегабайт, и в зависимости от скорости работы соединения пользователя скорость может сильно различаться. По этой причине я хочу помещать события в это, чтобы обрабатывать уведомление о ходе.Обработчики событий в конструкторах - возможно ли или даже мудро?
Вот мой вопрос: Могу ли я событие обработчиков в конструкторе или должен этот тип действия можно сделать с помощью метода в нагрузки?
Например:
public class MyObject
{
public event EventHandler<UpdateLoadProgressEventArgs> UpdateLoadProgress;
public MyObject(int id)
{
Background worker bgWorker = new BackgroundWorker();
bgWorker.DoWork += delegate(object s, DoWorkEventArgs args)
{
//load data and update progress incrementally
UpdateLoadProgress(this, new UpadteLoadProgressEventArgs(progressValue));
Result = someValue;
}
bgWorker.RunWorkAsync();
}
public int Result
{
get;
set;
}
}
Однако, когда я пытаюсь связать обработчики событий конструктору они всегда нуль, когда называют:
MyObject o = new MyObject(1);
o.UpdateLoadProgress += new EventHandler<EventArgs>(o_UpdateLoadProgress);
Я предполагаю, что это происходит потому, что I провод события после конструктора. Единственная альтернатива, которую я вижу, это создать метод Load, который выполняет работу конструктора. Недостатком является то, что любой, кто использует этот класс, должен знать, чтобы вызвать Load, прежде чем пытаться получить доступ к Result (или любому другому свойству).
EDIT: Вот окончательное решение:
MyObjectBuilder Класс
public class MyObjectBuilder
{
public event ProgressChangedEventHandler ProgressChanged;
public MyObject CreateMyObject()
{
MyObject o = new MyObject();
o.Load(ProgressChanged);
return o;
}
}
MyObject Класс
public class MyObject
{
public int Result { get; set;}
public void Load(ProgressChangedEventHandler handler)
{
BackgroundWorker bgWorker = new BackgroundWorker();
bgWorker.WorkerReportsProgress = true;
bgWorker.ProgressChanged += handler;
bgWorker.DoWork += delegate(object s, DoWorkEventArgs args)
{
for (int i = 0; i < 100; i++)
{
Thread.Sleep(10);
Result = i;
bgWorker.ReportProgress(i);
}
};
bgWorker.RunWorkerAsync();
}
}
Клас программы s
class Program
{
static void Main(string[] args)
{
MyObjectBuilder builder = new MyObjectBuilder();
builder.ProgressChanged += new ProgressChangedEventHandler(builder_ProgressChanged);
MyObject o = builder.CreateMyObject();
Console.ReadLine();
}
static void builder_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
Console.WriteLine(e.ProgressPercentage);
}
}
Обычно я обнаружил, что конструктор может загружать данные. Вы пожалеете об этом рано или поздно, и если вы проведете модульное тестирование, это будет «раньше». –