2009-05-15 13 views
6

का उपयोग करके एमवीपी पैटर्न मैं अपने डेटा को जारी रखने के लिए जेनेरिक रिपोजिटरी पैटर्न का उपयोग कर रहा हूं। पेज लोड पर, मैं एक नया रिपोजिटरी (आईरिपोजिटरी से) ऑब्जेक्ट बना रहा हूं, और पेजउनलोड पर, मैं इसका निपटान करता हूं।वेबफॉर्म और डी ऑब्जेक्ट इंस्टेंटेशन

masterpage/पृष्ठ प्रस्तोता को पारित करने के लिए वस्तुओं instantiating के आरोप में होना चाहिए या प्रस्तोता इस के आरोप में होना चाहिए? मैं पेजर (व्यू) की तुलना में प्रस्तुतकर्ता का परीक्षण करने के लिए अधिक चिंतित हूं क्योंकि प्रस्तुतकर्ता को दिए गए इंटरफेस को मॉक करना आसान है।

उदाहरण पृष्ठ

public partial class _Default : System.Web.UI.Page 
{ 
    private IRepository _repo; 
    protected void Page_Load(object sender, EventArgs e) 
    { 
     if (_repo == null) 
      _repo = new Repository(); 
     ConnectPresenter(); 
    } 

    private void ConnectPresenter() 
    { 
     _DefaultPresenter presenter = new _DefaultPresenter(_repo); 
    } 

    private void Page_Unload(object sender, EventArgs e) 
    { 
     if (_repo != null) 
      _repo.Dispose(); 
    } 
} 

ऐसी StructureMap या इस मामले में Ninject मदद के रूप में एक डि फ्रेमवर्क? क्या यह इस तरह की वस्तुओं का निपटान करने का प्रभारी होगा?

उत्तर

6

न तो पृष्ठ वर्ग है और न ही प्रस्तुतकर्ताओं निर्माण या उसके निर्भरता से किसी के जीवन चक्र के प्रबंधन के साथ सीधे निपटने के लिए होना चाहिए। चूंकि कन्स्ट्रक्टर इंजेक्शन वेबफॉर्म के साथ काम नहीं करता है, इसलिए आपको कक्षा में गुणों के रूप में किसी भी आवश्यक निर्भरता का पर्दाफाश करना होगा। उदाहरण के लिए, आप करने के लिए अपने वर्ग को बदल सकता है:

public partial class _Default : System.Web.UI.Page 
{ 
    protected void Page_Load(object sender, EventArgs e) 
    { 
    } 

    public _DefaultPresenter Presenter { get; set; } 
} 

पेज, भंडार के लिए किसी भी संदर्भ की जरूरत नहीं चाहिए क्योंकि यह प्रस्तोता में इंजेक्ट कर दिया जाएगा।

इस उत्तर के बाकी StructureMap के लिए विशिष्ट है - विवरण अन्य कंटेनरों के लिए अलग हो सकता है।

सेटर इंजेक्शन सक्षम करने के लिए, आप StructureMap बताने के लिए जो गुण को पॉप्युलेट करने की जरूरत है। एक तरीका यह है कि संपत्ति में [SetterProperty] विशेषता लागू करें। हालांकि, यह आपके वर्गों में स्ट्रक्चर मैप विवरण रखने के लिए थोड़ा आक्रामक महसूस कर सकता है। एक और तरीका स्ट्रक्चर मैप को कॉन्फ़िगर करना है ताकि यह जान सके कि कौन सी संपत्ति प्रकार इंजेक्ट करना है। उदाहरण के लिए:

protected void Application_Start(object sender, EventArgs e) 
{ 
    ObjectFactory.Initialize(x => 
    { 
     x.Scan(scan => 
     { 
      scan.TheCallingAssembly(); 
      scan.WithDefaultConventions(); 
     }); 
     x.ForRequestedType<IRepository>().TheDefaultIsConcreteType<Repository>().CacheBy(InstanceScope.Hybrid); 
     x.SetAllProperties(set => set.WithAnyTypeFromNamespaceContainingType<IRepository>()); 
    }); 
} 

SetAllProperties विधि आपको स्ट्रक्चर मैप को यह बताने की अनुमति देता है कि इसे किस संपत्ति को पॉप्युलेट करना चाहिए। इस मामले में, मैं सभी प्रस्तुतियों को इंजेक्ट करने के लिए स्ट्रक्चर मैप कह रहा हूं (मान लीजिए कि वे सभी एक ही नामस्थान में हैं)।

आपको अभी भी प्रत्येक अनुरोध पर सेटटर इंजेक्शन करने की आवश्यकता है।स्ट्रक्चर मैप के साथ, आप मौजूदा उदाहरण में निर्भरताओं को इंजेक्ट करने के लिए BuildUp() विधि का उपयोग करते हैं। आप इसे प्रत्येक पृष्ठ या पृष्ठ बेस क्लास की इनिट या लोड घटनाओं में कर सकते हैं, लेकिन फिर, यह आक्रामक लगता है। पूरी तरह से अपने पेज कक्षाओं से बाहर कंटेनर रखने के लिए, आप PreRequestHandlerExecute आवेदन की (Global.asax में या एक IHttpModule) घटना का उपयोग कर सकते हैं:, अंत में

protected void Application_PreRequestHandlerExecute(object sender, EventArgs e) 
{ 
    var application = (HttpApplication)sender; 
    var page = application.Context.CurrentHandler as Page; 
    if (page == null) return; 
    ObjectFactory.BuildUp(page); 
} 

अगर आप चाहते हैं करने के लिए स्पष्ट रूप से अपने IRepository का निपटान, आप कि संभाल सकता EndRequest स्थिति में:

protected void Application_EndRequest(object sender, EventArgs e) 
{ 
    var disposable = ObjectFactory.GetInstance<IRepository>() as IDisposable; 
    if (disposable != null) disposable.Dispose(); 
} 

ध्यान दें कि यह ठीक से काम करता है क्योंकि प्रारंभ में हम हाइब्रिड, जिसका अर्थ है द्वारा IRepository कैश करने के लिए StructureMap को बताया, "मुझे प्रत्येक HTTP अनुरोध के लिए एक ही उदाहरण (या धागा देते हैं, अगर एक वेबसाइट के भीतर नहीं चल रहा है) "। जब आप EndRequest में IRepository पुनर्प्राप्त करते हैं, तो आप अनुरोध के दौरान उपयोग किए गए वही प्राप्त करेंगे, और आप इसका निपटान कर सकते हैं।

2

हां, one of the walkthroughs out there of using DI with ASP.NET की जांच करने के लिए यह उचित होगा।

हाँ, प्रति-अनुरोध व्यवहार के निपटान उचित बिंदु पर वस्तुओं आम तौर पर ASP.NET के साथ कंटेनर के एकीकरण द्वारा किया जाता है।

सामान्य व्यवस्था यह है कि वस्तु निर्माण पृष्ठ और Application/Module के अंदर से बहती है। आम तौर पर आप [Inject] पर Page कक्षा पर गुणों को चिह्नित करते हैं, लेकिन यह इस बात पर निर्भर करता है कि आपने अपनी त्रिभुज की व्यवस्था कैसे की है। प्रेजेंटर आम तौर पर इसके परीक्षण या एएसपी.नेट कोटेक्स्ट के बावजूद इसकी आवश्यकता के बारे में घोषित करने के लिए कन्स्ट्रक्टो इंजेक्शन का उपयोग कर सकते हैं। फिर रनटाइम पर निर्भरता DI से संतुष्ट होगी। परीक्षण समय पर, आप अभी भी DI का उपयोग कर सकते हैं, हालांकि अन्य मामलों में केवल एसयूटी के साथ नकली गुच्छा बनाने और प्रेजेंटर को पास करने के लिए यह अधिक स्वाभाविक हो सकता है।

triead व्यवस्था wrt परीक्षण के बारे में, मैं this MSDN Mag article on using Ninject with xUnit.net by Justin Etheredge बहुत उपयोगी पाया, ASP.NET MVC में आते हैं, हालांकि निशाना बनाया। है कि सभी अपने कंटेनर द्वारा नियंत्रित किया जाना चाहिए -

+0

अपने प्रश्न में कोड या टैग को देखने के लिए खेद है! अब इसे फिर से काम किया है - आशा है कि मामलों में सुधार होगा! यदि आप अपना हटा देते हैं तो इसे हटा देंगे ... –