2012-06-02 10 views
9

समस्या (सार)Autofac - लाइफटाइम और मॉड्यूल

एक मॉड्यूल जो निर्भरता एक्स पंजीकृत करता निर्भरता एक्स एक MVC3 एप्लिकेशन में कोई भिन्न जीवनकाल (HttpRequest प्रति आजीवन) है को देखते हुए फिर एक सांत्वना आवेदन में (निर्भरता प्रति एक नाम के साथ lifetimescope)। निर्भरता एक्स के जीवनकाल को कहां या कैसे निर्दिष्ट करें?

प्रकरण

मैं इसमें एक मॉड्यूल जो सभी खजाने पंजीकृत करता है के साथ एक विधानसभा में अपने सभी डेटाबेस से संबंधित कोड डाल दिया है। अब मॉड्यूल में ISession (Nhibernate) पंजीकरण भी है।

ISession निर्भरता एक्स (दिए गए समस्या मामले में) है। एक एमवीसी 3 ऐप (आजीवन प्रति अनुरोध) में कंसोल ऐप में आईएसशन का अलग-अलग जीवनकाल होता है जहां मैं एक नामित लाइफटाइमस्कोप परिभाषित करता हूं।

क्या ISession का पंजीकरण मॉड्यूल के बाहर होना चाहिए? अजीब होगा क्योंकि यह एक कार्यान्वयन विस्तार है।

यहां करने का सबसे अच्छा मामला क्या है? डिजाइन दोष या इसके लिए स्मार्ट निर्माण कर रहे हैं :)?

+0

क्या आपके पास कनेक्शन के लिए दिमाग में विशिष्ट जीवनकाल है? यदि हां, तो क्या वे प्रति आवेदन अलग-अलग जीवनकाल हैं या क्या यह हमेशा आवेदन प्रकार के बावजूद समान है? पूलिंग के बारे में क्या? क्या आप कुछ ऐप्स में पूल करते हैं लेकिन दूसरों को नहीं? –

+0

ऐसा लगता है जैसे "एमवीसी एक्सटेंशन एक बार-प्रति-अनुरोध तंत्र प्राप्त करने के लिए एक नामित क्षेत्र का उपयोग करते हैं।" जब आप कंसोल ऐप में मॉड्यूल का उपयोग करते हैं तो एचटीपी नाम का दायरा वहां नहीं होता है। वर्तमान में मैं देख रहा हूं कि काम की इकाई क्या होगी और यह एक दायरे में encapsulated जाएगा। –

उत्तर

7

आपके उपयोग के मामले वर्णन देखते हुए, मैं कहेंगे आप विकल्पों में से कुछ है।

पहला, आप केवल प्रत्येक एप्लिकेशन को निर्भरता के अपने सेट दर्ज कर सकते हैं जिसमें जीवनकाल के दायरे शामिल हैं। इस संबंध में कोड के एक या दो "डुप्लिकेट" टुकड़े होने के कारण आवेदन के बीच मतभेदों और तथ्य यह है कि पंजीकरण काफी छोटे दिखाई देते हैं।

दूसरा, आप एक कंटेनरबिल्डर एक्सटेंशन विधि में सामान्य भाग (शून्य जीवनकाल स्कोप) को लपेट सकते हैं जिसका उपयोग प्रत्येक एप्लिकेशन में किया जा सकता है। इसका अभी भी मतलब होगा कि प्रत्येक ऐप में थोड़ा "डुप्लिकेट कोड" होता है लेकिन सामान्य तर्क एक साधारण एक्सटेंशन में लपेटा जाएगा।

public static IRegistrationBuilder<TLimit, ScanningActivatorData, DynamicRegistrationStyle> 
    RegisterConnection<TLimit, ScanningActivatorData, DynamicRegistrationStyle>(this ContainerBuilder builder) 
{ 
    // Put the common logic here: 
    builder.Register(...).AsImplementedInterfaces(); 
} 

प्रत्येक अनुप्रयोग में इस तरह के एक विस्तार उपभोक्ता दिखाई देगा: अंत में

builder.RegisterConnection().InstancePerHttpRequest(); 
// or 
builder.RegisterConnection().InstancePerLifetimeScope(); 

, यदि आप जानते हैं कि यह या तो वेब या गैर वेब है, अगर आप वह स्विच संभालती कस्टम मॉड्यूल बना सकता है :

+०१२३५१६४१०६१:

public class ConnectionModule : Autofac.Module 
{ 
    bool _isWeb; 
    public ConnectionModule(bool isWeb) 
    { 
    this._isWeb = isWeb; 
    } 

    protected override void Load(ContainerBuilder builder) 
    { 
    var reg = builder.Register(...).AsImplementedInterfaces(); 
    if(this._isWeb) 
    { 
     reg.InstancePerHttpRequest(); 
    } 
    else 
    { 
     reg.InstancePerLifetimeScope(); 
    } 
    } 
} 

प्रत्येक आवेदन में, आप तो मॉड्यूल रजिस्टर कर सकता है

// Web application: 
builder.RegisterModule(new ConnectionModule(true)); 

// Non-web application: 
builder.RegisterModule(new ConnectionModule(false)); 

वैकल्पिक रूप से, आपने अपने अन्य ऐप्स में अपने जीवनकाल के दायरे का उल्लेख किया है।आप बना सकते हैं अपने मॉड्यूल का नाम ले:

public class ConnectionModule : Autofac.Module 
{ 
    object _scopeTag; 
    public ConnectionModule(object scopeTag) 
    { 
    this._scopeTag = scopeTag; 
    } 

    protected override void Load(ContainerBuilder builder) 
    { 
    var reg = builder.Register(...) 
        .AsImplementedInterfaces() 
        .InstancePerMatchingLifetimeScope(this._scopeTag); 
    } 
} 

खपत समान है:

// Web application (using the standard tag normally provided): 
builder.RegisterModule(new ConnectionModule("httpRequest")); 

// Non-web application (using your custom scope name): 
builder.RegisterModule(new ConnectionModule("yourOtherScopeName")); 

मैं बस एक वेब अनुप्रयोग में InstancePerLifetimeScope का उपयोग कर जब तक कि वास्तव में आप क्या चाहते हैं के खिलाफ की सिफारिश करेंगे। जैसा कि अन्य उत्तरों/टिप्पणियों में उल्लेख किया गया है, InstancePerHttpRequest एक विशिष्ट नामित जीवनकाल क्षेत्र का उपयोग करता है ताकि बच्चे के जीवनकाल के क्षेत्र को सुरक्षित रखना सुरक्षित हो; InstancePerLifetimeScope का उपयोग इस तरह के प्रतिबंध नहीं है इसलिए आपको अनुरोध के लिए एक कनेक्शन के बजाय वास्तव में एक बच्चे के दायरे में एक कनेक्शन प्राप्त होगा। मैं, व्यक्तिगत रूप से, यह नहीं मानता कि अन्य डेवलपर बाल जीवनकाल के क्षेत्र (which is a recommended practice) का उपयोग नहीं करेंगे, इसलिए मेरे अनुप्रयोगों में मैं बहुत विशिष्ट हूं। यदि आप अपने आवेदन के कुल नियंत्रण में हैं और आप आश्वस्त कर सकते हैं कि आप अतिरिक्त बाल स्कॉप्स नहीं बना रहे हैं या आप वास्तव में प्रति कनेक्शन एक कनेक्शन चाहते हैं, तो शायद InstancePerLifetimeScope आपकी समस्या का समाधान करेगा।

+0

व्यापक उत्तर के लिए धन्यवाद! मैं इसके साथ आया हूं: https://gist.github.com/2883596 आप कॉन्फ़िगरेशन UnitOfWork को निर्भरता IUnitOfWork पर कॉन्फ़िगर करने के लिए कहते हैं जो कार्यान्वयन विवरण छुपाता है। यह समाधान एमवीसी 3 एक्सटेंशन पर निर्भर नहीं है। केवल इस समाधान के लिए नकारात्मक है कि आप केवल जीवन भर की अनुमति देने के दौरान सबकुछ कॉन्फ़िगर कर सकते हैं, दूर समझा जा सकता है, लेकिन अगर अभी के लिए कटौती करता है :) –

0

प्रति http अनुरोध के एक कनेक्शन का उपयोग करना आम बात है। यह मामला है, कनेक्शन का उपयोग किया जाएगा .InstansePerLifetimeScope()। उदाहरण के लिए, आप की तरह कुछ कर सकता:

builder 
    .Register(c => { 
         var conn = new SqlConnection(GetConnectionString()); 
         conn.Open(); 
         return conn; 
        }) 
    .AsImplementedInterfaces() 
    .InstancePerLifetimeScope(); 
+0

हाँ मुझे पता है कि आप ऐसा कर सकते हैं। मेरी समस्या यह है कि यह कहां करें? यह कुछ है 'डेटा' मॉड्यूल के लिए जिम्मेदार होना चाहिए। हालांकि मॉड्यूल के अंदर कनेक्शन को पंजीकृत करने और मॉड्यूल के बाहर जीवनकाल निर्धारित करने का कोई तरीका नहीं लगता है। –

+0

मैं कनेक्शन पंजीकृत करूँगा और जीवन मॉड्यूल को डेटा मॉड्यूल के अंदर सेट कर दूंगा। –

+0

एक एमवीसी ऐप में समस्या को थकाता है, जीवन भर एक कंसोल ऐप में भिन्न होता है जहां एचटीपी –