2013-09-02 5 views
6

समय के साथ नियंत्रक बहुत निर्भरता विकसित करते हैं, और प्रत्येक अनुरोध के लिए नियंत्रक का एक उदाहरण बनाते हैं (विशेष रूप से DI के साथ)। नियंत्रक सिंगलेट बनाने के लिए कोई समाधान है?नियंत्रक को एएसपी.नेट एमवीसी में प्रति आवेदन एक उदाहरण कैसे बनाया जाए?

+0

आप [अपने स्वयं के नियंत्रक कारखाना बनाने] कर सकते हैं आसानी से (http://www.dotnetcurry.com/ShowArticle.aspx?ID=878) ... लेकिन आप के संभावित कमियां के बारे में पूछ रहे हैं * * एक उदाहरण नियंत्रकों का उपयोग कर ? – bzlm

+1

असल में, मैंने पहले से ही अपने नियंत्रकों के प्रति उदाहरण प्रति एप्लिकेशन बना दिया है, लेकिन यह काम नहीं करता है: '.. अगर एक कस्टम नियंत्रक फैक्ट्री उपयोग में है, तो सुनिश्चित करें कि यह प्रत्येक के लिए नियंत्रक का एक नया उदाहरण बनाता है निवेदन।' – 6opuc

+5

हालांकि कुछ भी असंभव नहीं है, मेरा सुझाव है कि इसे लागू करने का प्रयास उत्तर से अधिक समस्याएं पैदा करेगा। उदाहरण के लिए नियंत्रक के उदाहरण की HttpContext प्रॉपर्टी उस अनुरोध के लिए स्पष्ट रूप से अद्वितीय है। संभवतः आप जिन समस्याओं का सामना कर सकते हैं उनमें से कई समस्याएं हैं। – Mark

उत्तर

16

नियंत्रकों के उदाहरण बनाना बहुत तेज और सरल संचालन है। जो भी महंगा हो जाता है वह प्रत्येक अनुरोध के लिए निर्भरता बना रहा है। तो, आपको वास्तव में जो कुछ चाहिए वह कई नियंत्रक हैं जो निर्भरताओं के समान उदाहरण साझा करते हैं।

उदा। आप नियंत्रक

public class SalesController : Controller 
{ 
    private IProductRepository productRepository; 
    private IOrderRepository orderRepository; 

    public SalesController(IProductRepository productRepository, 
          IOrderRepository orderRepository) 
    { 
     this.productRepository = productRepository; 
     this.orderRepository = orderRepository; 
    } 

    // ...  
} 

निम्नलिखित है आप सभी आवेदन के लिए खजाने के एक ही उदाहरणों का उपयोग करने के अपने निर्भरता इंजेक्शन ढांचे कॉन्फ़िगर करना चाहिए (ध्यान में रखना है, तो आप तुल्यकालन समस्या है सकते हैं)। अब निर्भरता बनाना अब महंगा नहीं है। सभी निर्भरताओं को केवल एक बार तत्काल किया जाता है, और सभी अनुरोधों के लिए पुन: उपयोग किया जाता है।

यदि आपके पास कई निर्भरताएं हैं और आप प्रत्येक निर्भरता के उदाहरण के संदर्भ में संदर्भ प्राप्त करने और नियंत्रक उदाहरण (जो मुझे नहीं लगता कि यह बहुत महंगा होगा) प्रदान करने की लागत के बारे में चिंता कर रहे हैं, तो आप अपनी निर्भरताओं को समूहित कर सकते हैं (कुछ की तरह परिचय पैरामीटर वस्तु रिफैक्टरिंग):

public class SalesController : Controller 
{ 
    private ISalesService salesService; 

    public SalesController(ISalesService salesService) 
    { 
     this.salesService = salesService; 
    } 

    // ...  
} 

public class SalesService : ISalesService 
{ 
    private IProductRepository productRepository; 
    private IOrderRepository orderRepository; 

    public SalesService(IProductRepository productRepository, 
          IOrderRepository orderRepository) 
    { 
     this.productRepository = productRepository; 
     this.orderRepository = orderRepository; 
    } 

    // ...  
} 

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

+1

बहुत अच्छा और विस्तृत एवर, धन्यवाद!नियंत्रक सिंगलेट बनाने के लिए कोई समाधान [हैक] नहीं है, यह मेरा आखिरी उपाय है ... बहुत अधिक रिफैक्टरिंग और एक्सएमएल-जादू (मैं वसंत का उपयोग कर रहा हूं) – 6opuc

+0

निश्चित रूप से सिंक्रनाइज़ेशन समस्याएं भुगतान करने के लिए बहुत अधिक कीमतें होंगी – user195166

1

तो सबसे पहले मूल प्रश्न का उत्तर:

public void ConfigureServices(IServiceCollection services) { 
    // put other services bindings here 

    // bind all Controller classes as singletons 
    services.AddSingleton<HomeController, HomeController>(); 

    // tell framework to obtain Controller instances from ServiceProvider. 
    services.AddMvc().AddControllersAsServices(); 
} 

के रूप में, मूल प्रश्न में कहा गया है, तो नियंत्रक बड़ा निर्भरता मुख्य रूप से अनुरोध scoped या क्षणिक निर्भरता से मिलकर फिर उन्हें प्रत्येक अनुरोध हो सकता है के लिए अलग से बनाने पेड़ आपके आवेदन की स्केलेबिलिटी पर कुछ पदचिह्न (जावा में उदाहरण के लिए सर्वलेट उदाहरण इस कारण से डिफ़ॉल्ट रूप से सिंगलेट्स हैं)। जबकि आमतौर पर एक बड़ा निर्भरता पेड़ बनाने के लिए आवश्यक सीपीयू और वास्तविक समय नगण्य होता है (जब तक कि आपके घटकों के रचनाकारों में कुछ भारी गणना या नेटवर्क संचार न हो, जो क्षणिक या अनुरोधित स्कोप्ड घटकों के लिए लगभग एक अच्छा विचार नहीं है), स्मृति उपयोग पदचिह्न के साथ गणना करने के लिए कुछ है। सामान्य डीबी-वेब ऐप्स मेमोरी के मामले में मुख्य कारक समवर्ती अनुरोधों की संख्या सीमित करता है जो एकल मशीन-नोड संभाल सकता है। यदि प्रत्येक अनुरोध में एक बड़े निर्भरता पेड़ की एक अलग प्रति है, तो वे एक बड़ी मात्रा में स्मृति का उपभोग कर सकते हैं (दूसरी चीज देखने के लिए एक नए थ्रेड के लिए प्रारंभिक ढेर आकार है)।

स्वीकृत उत्तर 1220560 समस्या को हल करता है, लेकिन मैं इसे एक बदसूरत हैक मानता हूं और इसमें कुछ कमीएं हैं: आपको इस कृत्रिम सिंगलटन सेवा को बनाने की आवश्यकता है जिसका उपयोग आपके नियंत्रकों द्वारा या तो सेवा लोकेटर या एक के रूप में किया जाएगा अन्य सेवाओं के लिए प्रॉक्सी। यदि आपके पास अपने सभी नियंत्रकों के लिए केवल एक ही सिंगलटन ऑब्जेक्ट है तो आप अपने कंट्रोलर की वास्तविक निर्भरताओं को प्रभावी ढंग से छुपा रहे हैं: उदाहरण के लिए यदि कोई आपके नियंत्रक के लिए यूनिट-टेस्ट लिखना चाहता है तो उसे यह देखने के लिए सावधानी से विश्लेषण करना होगा कि वास्तव में कौन सी निर्भरताओं उपयोग करता है, ताकि वह जानता हो कि उसे अपने परीक्षण सेटअप में क्या मोक्स/नकल प्रदान करने की आवश्यकता है। यदि बाद में आप अपना कंट्रोलर बदलते हैं और आपके परिवर्तन के परिणामस्वरूप आपके नियंत्रक सेवाओं का सबसेट भी बदलता है, तो टेस्ट सेटअप को अपडेट करना भी भूलना बहुत आसान है। यह कभी-कभी उन बगों का कारण बन सकता है जो ट्रैक करना मुश्किल होता है। इसके विपरीत, यदि आपकी निर्भरता स्पष्ट रूप से कन्स्ट्रक्टर पैरा के रूप में घोषित की जाती है, तो आपको तुरंत परीक्षण सेटअप में एक कंपाइलर त्रुटि मिल जाएगी।एक और चीज जो आप कर सकते हैं वह प्रत्येक नियंत्रक के लिए एक अलग सिंगलटन प्रॉक्सी/सेवा लोकेटर है, लेकिन फिर यह मूल रूप से बहुत परेशानी है।

भले ही आप मेरे द्वारा प्रस्तावित समाधान का उपयोग करते हैं या उत्तर # 1220560 से आपको समाधान को इंजेक्शन देते समय सावधान रहना चाहिए, अनुरोध के इंजेक्शन के दौरान https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection#registering-your-own-services में वर्णित सिंगलटन ऑब्जेक्ट्स में स्कोप्ड निर्भरताएं "पंजीकरण-अपनी-स्वयं-सेवाओं के अंत में " अनुभाग। आप इस समस्या को यहाँ करने के लिए संभव समाधान पा सकते हैं: how to use scoped dependency in a singleton in C#/ASP के लिए देखने के लिए एक और बात संगामिति मुद्दा है: सिंगलटन वस्तुओं विभिन्न समवर्ती अनुरोधों को संभालने के कई सूत्र द्वारा समवर्ती पहुँचा जा सकता है, इसलिए किसी भी गैर धागा सुरक्षित संसाधनों के उचित तुल्यकालन जोड़ना सुनिश्चित करें आपका सिंगलटन उपयोग करता है।

संपादित करें:

मैं सिर्फ महसूस किया गया है मूल प्रश्न ASP.NET के बारे में था और इस उत्तर ASP.NET कोर के लिए है, इसलिए यह शायद "गैर कोर" के लिए काम नहीं करेगा।

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