2009-11-30 11 views
12

मेरे पास कई निर्भरता इंजेक्शन सेवाएं हैं जो HTTP संदर्भ जैसी सामग्री पर निर्भर हैं। अभी मैं उन्हें सिंगलटन एप्लिकेशन_स्टार्ट हैंडलर में विंडसर कंटेनर के रूप में कॉन्फ़िगर कर रहा हूं, जो स्पष्ट रूप से ऐसी सेवाओं के लिए एक समस्या है।एएसपी.नेट एमवीसी और विंडसर। कैसल: एचटीपीकॉन्टेक्स्ट-निर्भर सेवाओं के साथ काम करना

इसे संभालने का सबसे अच्छा तरीका क्या है? मैं उन्हें क्षणिक बनाने और फिर प्रत्येक HTTP अनुरोध के बाद उन्हें जारी करने पर विचार कर रहा हूं। लेकिन उनमें HTTP संदर्भ इंजेक्ट करने का सबसे अच्छा तरीका/स्थान क्या है? नियंत्रक कारखाना या कहीं और?

उत्तर

5

कैसल विंडसर के साथ आप PerWebRequest जीवनकाल का उपयोग कर सकते हैं - जो आपकी आवश्यकताओं के साथ बहुत अच्छी तरह से फिट होना चाहिए।

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

+0

मार्क, जानकारी के लिए धन्यवाद - मुझे PerWebRequest के बारे में पता नहीं था। मैं इसे देख लूँगा। –

+0

मार्क, मैंने PerWebRequest में देखा है, लेकिन मुझे अभी भी नहीं पता है कि सेवाएं HttpContext कैसे प्राप्त कर सकती हैं। जब मैं स्वयं को कंटेनर में HttpContextBase का उदाहरण पंजीकृत करने का प्रयास करता हूं, तो यह दूसरे अनुरोध के बाद विफल रहता है (चूंकि एक उदाहरण पिछले अनुरोध में पहले ही पंजीकृत था)। मुझे अब तक Google पर कुछ भी नहीं मिला ... –

+0

मैंने गलत समझा होगा कि आप क्या करने का प्रयास कर रहे हैं, लेकिन आप एप्लिकेशन_स्टार्ट से HttpContext का उपयोग नहीं कर सकते हैं क्योंकि इस बिंदु पर * है * कोई HttpContext (PerWebRequest या कोई PerWebRequest नहीं है)। अब जब मैं इसके बारे में सोचता हूं, तो डी कंटेनर से HttpContext के जीवनकाल को नियंत्रित करने का प्रयास करने का कोई मतलब नहीं है, क्योंकि यह जीवनकाल पहले से ही एएसपी.नेट एमवीसी ढांचे द्वारा प्रबंधित किया जा रहा है।आप * क्या कर सकते हैं एक कस्टम आईसींट्रोलर फैक्ट्री में हुक करना और उस बिंदु पर आपके द्वारा प्रदान की गई HttpContext को पकड़ना है, और फिर उस पर निर्भर करता है कि बाकी सब कुछ तार करने के लिए एक कारखाने विधि का उपयोग करें। –

24

मार्क की तरह ही, आपको इन http- निर्भर सेवाओं को या तो PerWebRequest या क्षणिक के रूप में पंजीकृत करने की आवश्यकता है।

public class Service { 
    private readonly HttpRequestBase request; 

    public Service(HttpRequestBase request) { 
     this.request = request; 
    } 

    public string RawUrl { 
     get { 
      return request.RawUrl; 
     } 
    } 
} 

... 

protected void Application_Start(object sender, EventArgs e) { 
    IWindsorContainer container = new WindsorContainer(); 
    container.AddFacility<FactorySupportFacility>(); 
    container.AddComponentLifeStyle<Service>(LifestyleType.Transient); 

    container.Register(Component.For<HttpRequestBase>() 
     .LifeStyle.PerWebRequest 
     .UsingFactoryMethod(() => new HttpRequestWrapper(HttpContext.Current.Request))); 

    container.Register(Component.For<HttpContextBase>() 
     .LifeStyle.PerWebRequest 
     .UsingFactoryMethod(() => new HttpContextWrapper(HttpContext.Current))); 
} 

HttpRequestBase बजाय HttpRequest का उपयोग कर आप आसानी से इसे परीक्षण के लिए बाहर नकली कर सकते हैं द्वारा: यहां नमूने के रजिस्टर और इंजेक्षन एक HttpRequest या HttpContext करने के लिए कैसे पता चलता है कि है। इसके अलावा, अपने वेब.कॉन्फिग में PerWebRequestLifestyleModule पंजीकृत करना न भूलें।

+0

धन्यवाद मॉरिसियो, यह कुछ ऐसा है जिसे मैं ढूंढ रहा था। –

+0

दोहराने के लायक हो सकता है कि आपको लाइन जोड़ने की आवश्यकता है: कंटेनर। AddFacility (); यह मेरे लिए एक छोटा सा गॉचा था कि मैंने पहले पढ़ने पर आपके उदाहरण को याद किया। मदद के लिए धन्यवाद, बहुत उपयोगी! – ArtificialGold

+0

विंडसर 2.5 के रूप में, इस मामले के लिए अब 'फैक्ट्रीस्पोर्टफैसिलिटी' की आवश्यकता नहीं है। –

4

मैं बस इसी सटीक समस्या में भाग गया, लेकिन मेरा समाधान कुछ अलग है।

इंटरफ़ेस:

public interface IHttpContextProvider 
{ 
    /// <summary> 
    /// Gets the current HTTP context. 
    /// </summary> 
    /// <value>The current HTTP context.</value> 
    HttpContextBase Current { get; } 
} 

कार्यान्वयन:

/// <summary> 
/// A default HTTP context provider, returning a <see cref="HttpContextWrapper"/> from <see cref="HttpContext.Current"/>. 
/// </summary> 
public class DefaultHttpContextProvider : IHttpContextProvider 
{ 
    public HttpContextBase Current 
    { 
     get { return new HttpContextWrapper(HttpContext.Current); } 
    } 
} 

मैं तो रजिस्टर कंटेनर में एक सिंगलटन के रूप में IHttpContextProvider। जब मैं DI की बात करता हूं, तब भी मैं नौसिखिया का थोड़ा सा हूं, इसलिए शायद मैं जटिल चीजों से अधिक हूं, लेकिन जो मैं समझ सकता हूं, उससे कोई भी सिंगलटन घटक PerWebRequest लाइफस्टाइल घटकों पर निर्भर नहीं हो सकता है, जो समझ में आता है (लेकिन यही सब उदाहरण हैं)। मेरे समाधान में, मैं एक पृथक घटक में HttpContext.Current पर निर्भर करता हूं और मुझे इसका परीक्षण करने में कोई दिलचस्पी नहीं है। लेकिन प्रत्येक घटक जिसे HTTP संदर्भ तक पहुंच की आवश्यकता है, वह IHttpContextProvider के आधार पर प्राप्त कर सकता है और आवश्यकतानुसार आसानी से नकल कर सकता है।

क्या मैं वास्तव में जटिल चीजों से अधिक हूं या क्या मेरे समाधान में कोई चेतावनी है?

+1

मुझे उल्लेख करना चाहिए, इस तरह, वर्तमान HTTP संदर्भ पर निर्भर मेरी कोई भी सेवा PerWebRequest/क्षणिक के रूप में पंजीकृत होने की आवश्यकता नहीं है। – Siewers

+0

यह अच्छा काम करता है, धन्यवाद। –

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

  • कोई संबंधित समस्या नहीं^_^