2008-10-09 14 views
11

एमवीपी का उपयोग करके, निर्माण और निर्भरता इंजेक्शन का सामान्य क्रम क्या है।एमवीपी निर्भरता इंजेक्शन

आमतौर पर आप प्रत्येक दृश्य के लिए प्रस्तुति बनाते हैं और प्रस्तुतकर्ता को प्रस्तुतकर्ता में दृश्य पास करते हैं। लेकिन अगर आपके पास है:

  1. ऐसी सेवा जो कई विचारों को घटनाओं को सुनने की आवश्यकता होती है।
  2. एक ही डेटा मॉडल कैश को इंगित करने वाले एकाधिक विचार।

कोई उपयोगकर्ता से जानकारी का सामान्य प्रवाह प्रदर्शित कर सकता है जो किसी सर्वर से सेवा में वापस आने वाले डेटा पर क्लिक करता है।

पहले, मैं शोध करे इंटरफेस को परिभाषित:

उत्तर

12

यहाँ मैं क्या करते हैं

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. मैं कंटेनर में MyPresenter के लिए पूछता हूं।
  4. कंटेनर instanciate एक MyView
  5. यह एक MyPresenter
  6. instanciates यह AbstractPresenter.View संपत्ति के माध्यम से प्रस्तोता में दृश्य इंजेक्षन।
  7. सेटर कोड द्वि-दिशात्मक संघ
  8. कंटेनर रिटर्न जोड़ी प्रस्तुतकर्ता/देखें

यह आप दोनों अपने दृश्य और अपने प्रस्तोता में अन्य निर्भरता (सेवाओं, रेपोस) इंजेक्षन करने की अनुमति देता पूरा करती है। लेकिन परिदृश्य में आपने वर्णन किया है, मैं आपको सलाह देता हूं कि दृश्य के बजाय प्रस्तुतकर्ता में सेवाओं और कैश को इंजेक्ट करने की सलाह दी गई है।

+1

आप IDISposable चिंताओं को कैसे संभालेंगे? विशेष रूप से, कचरा संग्रह की अनुमति देने के लिए गोलाकार संदर्भ तोड़ना? – aboy021

7

WinForms में, मैं एक साधारण दृष्टिकोण पसंद करता हूं। आमतौर पर आप डिज़ाइन सतह पर कुछ उपयोगकर्ता नियंत्रणों से निपट रहे हैं - इन्हें अपने व्यू क्लास बनाएं। .NET आपके लिए नियंत्रण पदानुक्रम बनाता है (InitializeComponent के माध्यम से)। यदि आप Passive 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; 
    } 
} 

आप (आईओसी का उपयोग कर और (प्रस्तुतकर्ता वर्ग में) IModel के कार्यान्वयन के लिए अपने आईओसी कंटेनर पूछ और IPresenter द्वारा एक कदम और आगे इस उदाहरण दसगुणा सकते में व्यू क्लास)।

0
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; 
     } 
    } 
} 
+2

क्या आप कृपया अपना कोड टिप्पणी कर सकते हैं? –

संबंधित मुद्दे