Шаблон стратегии и внедрение зависимостей с использованием Unity

Иногда компонент Timer полезен и легко настраивается в WinForms, просто устанавливает его интервал и затем включает его, а затем убедитесь, что первое, что вы делаете в обработчике событий Tick, - это отключить себя.

Я думаю, что Timer запускает код в своем собственном потоке, поэтому вам может понадобиться выполнить BeginInvoke (вызываемый объектом WinForm [this]) для запуска вашего действия.

private WebBrowserDocumentCompletedEventHandler handler; //need to make it a class field for the handler below (anonymous delegates seem to capture state at point of definition, so they can't capture their own reference)
private string imageFilename;
private bool exit;

public void CaptureScreenshot(Uri address = null, string imageFilename = null, int msecDelay = 0, bool exit = false)
{
  handler = (s, e) =>
   {
     webBrowser.DocumentCompleted -= handler; //must do first

     this.imageFilename = imageFilename;
     this.exit = exit;

     timerScreenshot.Interval = (msecDelay > 0)? msecDelay : 1;
     timerScreenshot.Enabled = true;
   };

  webBrowser.DocumentCompleted += handler;
  Go(address); //if address == null, will use URL from UI
}

private void timerScreenshot_Tick(object sender, EventArgs e)
{
  timerScreenshot.Enabled = false; //must do first

  BeginInvoke((Action)(() => //Invoke at UI thread
  { //run in UI thread

    BringToFront();
    Bitmap bitmap = webBrowser.GetScreenshot();

    if (imageFilename == null)
      imageFilename = bitmap.ShowSaveFileDialog();

    if (imageFilename != null)
    {
      Directory.CreateDirectory(Path.GetDirectoryName(Path.GetFullPath(imageFilename))); //create any parent directories needed
      bitmap.Save(imageFilename);
    }

    bitmap.Dispose(); //release bitmap resources

    if (exit)
      Close(); //this should close the app, since this is the main form

  }), null);
}

вы можете увидеть выше в действии в инструменте WebCapture ( http://gallery.clipflair.net/WebCapture , исходный код: http://ClipFlair.codeplex.com , см. раздел «Инструменты / Веб-камера»), который захватывает скриншоты с веб-сайтов. BTW, если вы хотите вызвать исполняемый файл из командной строки, убедитесь, что вы перешли в «Свойства проекта» и на вкладке «Безопасность» отключите защиту ClickOnce (иначе он не сможет получить доступ к командной строке)

24
задан Mathias 10 November 2009 в 06:50
поделиться

1 ответ

Общий шаблон в DI состоит в том, что во время выполнения будет только одна реализация данной абстракции. Это просто делает жизнь намного проще, так как вам не нужно иметь дело с неоднозначностью, такой как та, которую вы описываете.

Однако иногда вам нужно изменить реализацию в зависимости от контекста, например, приведенный вами пример . Многие контейнеры DI предоставляют способы, с помощью которых вы можете указать квалифицирующий параметр, но это означает, что в конечном итоге вы будете жестко привязать свой код к конкретному контейнеру DI.

Намного лучшим решением было бы введение Abstract Factory ], которые могут предоставить то, что вам нужно. Что-то вроде

public interface ICarFactory
{
    Car Create(IEngine engine);
}

Если вам нужно внедрить больше стратегий, возможно, шаблон проектирования Builder может подойти еще лучше.

В любом случае, Дело в том, что вместо регистрации множества разных автомобилей в контейнере вы должны вместо этого зарегистрировать одну реализацию ICarFactory.

В вашем клиентском коде вы должны использовать внедренный ICarFactory для создания экземпляра Car на основе определенного IEngine.

var car = factory.Create(engine);
27
ответ дан 29 November 2019 в 00:10
поделиться
Другие вопросы по тегам:

Похожие вопросы: