문제

MVP를 사용하면 정상적인 구조 및 의존성 주입 순서는 얼마입니까?

일반적으로 각보기에 대한 발표자를 생성하고 뷰를 생성자의 발표자에게 전달합니다. 그러나 당신이 가지고 있다면?

  1. 여러 조회수가 이벤트를 듣는 데 필요한 서비스.
  2. 다중 뷰는 모두 동일한 데이터 모델 캐시를 가리키는다.

누군가가 사용자에서 서버에서 서비스로 돌아 오는 데이터로의 일반 정보 흐름을 표시 할 수 있습니까?

도움이 되었습니까?

해결책

여기에 내가하는 일이 있습니다.

먼저이 인터페이스를 정의합니다.

public interface IView<TPresenter>
{
    TPresenter Presenter { get; set; }
}

public interface IPresenter<TView, TPresenter>
    where TView : IView<TPresenter>
    where TPresenter : IPresenter<TView, TPresenter>
{
    TView View { get; set; }
}

그런 다음이 추상 발표자 수업 :

public abstract class AbstractPresenter<TView, TPresenter> : IPresenter<TView, TPresenter>
    where TView : IView<TPresenter>
    where TPresenter : class, IPresenter<TView, TPresenter>
{
    protected TView view;

    public TView View
    {
        get { return this.view; }
        set
        {
            this.view = value;
            this.view.Presenter = this as TPresenter;
        }
    }
}

뷰는 생성자 대신 속성을 통해 주입하여 세터의 양방향 애정을 허용합니다. 안전한 캐스트가 필요합니다 ...

그런 다음 내 콘크리트 발표자는 다음과 같습니다.

public class MyPresenter : AbstractPresenter<IMyView, MyPresenter>
{
    //...
}

어디에 IMyView 구현 IView. 콘크리트 뷰 유형이 존재해야합니다 (예 : MyView), 그러나 그것은 그것을 해결하는 용기입니다.

  1. 나는 등록한다 MyPresenter 일시적인 동작으로 컨테이너에 자체를 입력하십시오.
  2. 나는 등록한다 MyView 로서 IMyView 일시적 동작이있는 컨테이너에서.
  3. 그런 다음 a MyPresenter 컨테이너로.
  4. 컨테이너는 Myview를 시동합니다
  5. 그것은 a MyPresenter
  6. 그것은 발표자에게보기를 주입합니다 AbstractPresenter.View 재산.
  7. 세터 코드는 양방향 협회를 완료합니다
  8. 컨테이너는 커플 발표자/보기를 반환합니다

그것은 당신이 당신의 견해와 발표자 모두에 다른 종속성 (서비스, 저장소)을 주입 할 수있게합니다. 그러나 설명한 시나리오에서는 서비스와 캐시를 주입하는 것이 좋습니다. 증여자,보기 대신.

다른 팁

Winforms에서는 간단한 접근 방식을 선호합니다. 일반적으로 디자인 표면에서 몇 가지 USERCONTROL을 다루고 있습니다. .NET은 (InitializeComponent를 통해) 귀하를위한 제어 계층 구조를 만듭니다. 당신이 사용하는 경우 수동적 견해 패턴, 각보기는 발표자를 인스턴스화합니다. (직접 또는 IOC 컨테이너를 요청하여이를 수행 할 수 있습니다.) 생성자 주입을 사용하여 뷰의 인터페이스에 대한 참조를 발표자의 생성자에 전달하십시오. 그런 다음 발표자는 이벤트를 볼 수 있도록 스스로를 연결할 수 있습니다. 모델의 프로세스를 반복하십시오. 발표자는 모델을 인스턴스화하고 이벤트까지 전선합니다. (이 경우 수동적 견해가 발표자가 모델에 대한 참조를 유지한다고 말하면 생성자 주입이 필요하지 않습니다.

이 접근법에서 찾은 유일한 NIT는 모델과 발표자의 수명을 올바르게 관리하는 것입니다. 당신은 가능한 한 간단하게보기를 원하므로 발표자에 대한 참조를 유지하는 것을 원하지 않을 것입니다. 그러나 이는이 발표자 객체가 귀하의 견해에 묶인 이벤트 핸들러와 매달려 있음을 의미합니다. 이 설정은 당신의 견해가 쓰레기 수집되는 것을 방지합니다. 한 가지 해결책은 View가 폐쇄되었음을 나타내는 이벤트를 게시하도록하는 것입니다. 발표자는 이벤트를 받고 모델과 뷰 구독을 모두 제거합니다. 웹의 객체가 이제 제대로 해석되고 쓰레기 수집기가 작업을 수행 할 수 있습니다.

당신은 다음과 같은 것과 같은 것입니다.

public interface IView
{
   ...
   event Action SomeEvent;
   event EventHandler Disposed;
   ...
}

// Note that the IView.Disposed event is implemented by the 
// UserControl.Disposed event. 
public class View : UserControl, IView
{
   public event Action SomeEvent;

   public View()
   {
      var presenter = new Presenter(this);
   }
}

public interface IModel
{
   ...
   event Action ModelChanged;
   ...
}

public class Model : IModel
{
   ...
   public event Action ModelChanged;
   ...
}

public class Presenter
{
   private IView MyView;
   private IModel MyModel;

   public Presenter(View view)
   {
      MyView = view;
      MyView.SomeEvent += RespondToSomeEvent;
      MyView.Disposed += ViewDisposed;

      MyModel = new Model();
      MyModel.ModelChanged += RespondToModelChanged;
   }

   // You could take this a step further by implementing IDisposable on the
   // presenter and having View.Dispose() trigger Presenter.Dispose().
   private void ViewDisposed(object sender, EventArgs e)
   {
      MyView.SomeEvent -= RespondToSomeEvent;
      MyView.Disposed -= ViewDisposed;
      MyView = null;

      MyModel.Modelchanged -= RespondToModelChanged;
      MyModel = null;
   }
}

IOC를 사용하고 IOC 컨테이너에 IMODEL (발표자 클래스) 및 IPRESENTER (View Class)의 구현을 요청 하여이 예제를 한 단계 더 해체 할 수 있습니다.

interface IEmployee
{
    int EmployeeId {get;}
    string FirstName {get;}
    string LastName {get;}
}
interface IEmployeeRepository
{
    void SaveEmployee(IEmployee employee);
    IEmployee GetEmployeeById(int employeeId);
    IEmployee[] Employees { get; }
}
interface IEmployeeView
{
    event Action<IEmployee> OnEmployeeSaved;
}

interface IEmployeeController
{
    IEmployeeView View {get;}
    IEmployeeRepository Repository {get;}
    IEmployee[] Employees {get;}        
}

partial class EmployeeView: UserControl, IEmployeeView
{
    public EmployeeView()
    {
        InitComponent();
    }
}
class EmployeeController:IEmployeeController
{
    private IEmployeeView view;
    private IEmployeeRepository repository;
    public EmployeeController(IEmployeeView view, IEmployeeRepository repository)
    {
        this.repository = repository;
        this.view = view;
        this.view.OnEmployeeSaved+=new Action<IEmployee>(view_OnEmployeeSaved);
    }

    void  view_OnEmployeeSaved(IEmployee employee)
    {
        repository.SaveEmployee(employee);
    }
    public IEmployeeView View 
    {
        get
        { 
            return view;
        }
    }
    public IEmployeeRepository Repository
    {
        get
        {
            return repository;
        }
    }

    public IEmployee[] Employees
    {
        get 
        {
            return repository.Employees;
        }
    }
}

WinFormsMVP는 Windows 양식을위한 매우 우수한 MVP 프레임 워크입니다. 이 프레임 워크를 사용하여 여러 뷰에서 쉽게 서비스를 주입 할 수 있습니다. 이것 샘플 소스 코드가있는 좋은 기사는 프레임 워크 사용 방법을 설명합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top