2011-08-26 15 views
21

का उपयोग कर बेस क्लास में कन्स्ट्रक्टर इंजेक्शन मेरे पास एक सार आधार नियंत्रक है जिसमें एक कन्स्ट्रक्टर है जिसे मैं आशा करता हूं कि नियंत्रकों के निर्माण के दौरान ऑटोफैक द्वारा पॉप्युलेट किया जाएगा।ऑटोफैक

public abstract class BaseController : Controller 
{ 
    protected ILogger { get; private set; } 

    protected BaseController() 
    { 
    } 

    protected BaseController(ILogger logger) 
    { 
     Logger = logger; 
    } 
} 

यह तब से काम नहीं करता जब मैं इससे नियंत्रक प्राप्त करता हूं।

मैं इसे केवल काम करने के लिए प्राप्त कर सकता हूं जब मैं स्पष्ट रूप से नियंत्रक से कन्स्ट्रक्टर को स्पष्ट रूप से कॉल करता हूं। क्या यह करने का सही तरीका है?

public class PublicController : BaseController 
{ 
    public PublicController() 
    { 
    } 

    public PublicController(ILogger logger) : base(logger) 
    { 

    } 
} 

इसके अलावा, MVC एकीकरण विधानसभा का उपयोग कर, वहाँ कंटेनर अन्य वर्गों के लिए अपने स्वयं के समाधान करने के लिए साझा करने के लिए एक तरह से होने लगते हैं नहीं करता है। मैंने कहीं पढ़ा है कि इसे प्रोत्साहित नहीं किया जाता है, क्यों नहीं? क्या यह सिर्फ किसी भी एकल आईओसी ढांचे की निर्भरता को कम करने के लिए है? कन्स्ट्रक्टर इंजेक्शन केवल हैराची के नीचे निर्भरता को पॉप्युलेट करने का तरीका है।

धन्यवाद

उत्तर

48

बेस क्लास कन्स्ट्रक्टर को कॉल करना स्पष्ट रूप से सी # में कन्स्ट्रक्टर इंजेक्शन का उपयोग करने का एकमात्र तरीका है। ऐसा लगता है कि आपको BaseController और PublicController से पैरामीटर रहित कन्स्ट्रक्टर को हटा देना चाहिए क्योंकि लॉगर उपलब्ध होने पर उन्हें वास्तव में कभी नहीं कहा जाना चाहिए।

आधार नियंत्रक में निर्भरता इंजेक्शन की समस्या एएसपी.नेट एमवीसी और आईओसी का उपयोग कर एक आम है। विचार के कई विकल्प/स्कूल हैं।

1.) कुल सेवाओं का उपयोग करें। व्युत्पन्न वर्ग कन्स्ट्रक्टर को सरल रखने के लिए, बेस कंट्रोलर (उदा। IBaseControllerDependencies या इसी तरह की सभी आवश्यक सेवाओं को प्रदर्शित करने वाली सभी अलग-अलग सेवाओं को प्रदर्शित या प्रतिनिधि करने वाली एक सेवा बनाएं।) फिर ILogger के साथ इस सेवा को BaseController पर पास करें।

आपके आवेदन और आपके द्वारा उपयोग किए जा रहे बेस क्लास की संख्या के आधार पर विभिन्न पेशेवर/विपक्ष हैं।इस पर और अधिक देखने के लिए Google 'ऑटोफैक कुल सेवाओं' के लिए।

2.) संपत्ति इंजेक्शन का उपयोग करें। अपने आधार वर्ग सार्वजनिक पर ILogger संपत्ति है, और का उपयोग कर कंटेनर कॉन्फ़िगर करें:

builder.RegisterControllers().PropertiesAutowired(); 

संपत्ति इंजेक्शन वास्तव में Autofac में एक पसंदीदा तकनीक नहीं है। निर्भरता स्वीकार करने के लिए कन्स्ट्रक्टर की भूमिका है, जबकि लिखने योग्य गुणों को अक्सर कोड गंध के रूप में देखा जाता है, इसलिए ऑटोफ़ैक वास्तव में इस मामले के लिए अनुकूलित नहीं होता है। दोषों में से एक यह है कि लिखने योग्य गुण इंजेक्शन नहीं होना चाहिए, अक्सर अजीब परिणामों के साथ गलती से होते हैं।

3.) विभिन्न एक्शन फ़िल्टर में रिएक्टर आधार नियंत्रक कार्यक्षमता। ऑटोफैक एमवीसी एक्शन इनवोकेशन पाइपलाइन में एक्शन फ़िल्टर इंजेक्ट कर सकता है। इस प्रकार फ़िल्टर बेस क्लास पर निर्भरताएं ले सकते हैं, और एक ही चिंता को क्रॉस-कटिंग तरीके में लागू किया जा सकता है। वेब पर इस बारे में अधिक जानकारी, ExtensibleActionInvoker और .InjectActionInvoker() आपको जिस जानकारी की आवश्यकता होगी उसे इंगित करें। सभी चिंताओं के साथ हमेशा संभव नहीं है।

4, आपके दूसरे प्रश्न का उत्तर भी।) DependencyResolver.Current से सेवा स्थान का उपयोग कर आधार नियंत्रक निर्भरताओं को हल करें।

var logger = DependencyResolver.Current.GetService<ILogger>(); 

कारण यह प्रोत्साहित नहीं किया गया है कि यह जिसके परिणामस्वरूप आवेदन कठिन बना देता है समझने के लिए, क्योंकि यह अब संभव नहीं है देखने के लिए क्या एक घटक सेवाएँ एक ही स्थान पर देख कर पर निर्भर करता है है (निर्माता।) निर्धारित करने के लिए किसी विशेष घटक का उपयोग करने से पहले कंटेनर में कॉन्फ़िगर किया जाना चाहिए, GetService() कॉल खोजने के लिए किसी को घटक के पूरे कोडबेस को देखना होगा। यूनिट परीक्षण करते समय एक उल्लेखनीय बाधा।

उम्मीद है कि यह मदद करता है, मस्तिष्क डंप का थोड़ा सा मुझे पता है :) अन्य शायद इनके लिए कुछ और विचार जोड़ सकते हैं।

2

मैं और अधिक विस्तार के लिए पूछने की टिप्पणी विशेषाधिकार नहीं हैं, लेकिन मैं समझने के लिए आप क्या उम्मीद है और क्यों कंटेनर उन अपेक्षाओं को पूरा नहीं कर रहा है अपना पंजीकरण कोड देखने की जरूरत होगी।

आपके अतिरिक्त प्रश्नों के अनुसार: कक्षा के लिए अपने स्वयं के समाधान करने के लिए एक तरीका नहीं है, लेकिन एक वर्ग एक ज्ञात प्रकार (जो अक्सर अक्सर पर्याप्त) के लिए स्वचालित रूप से हल करने योग्य ऑब्जेक्ट फैक्ट्री पर निर्भरता ले सकता है। अगर आपने A पंजीकृत किया है, तो आप Func<A> पर निर्भरता ले सकते हैं। Autofac में इस तरह के कई रिश्ते प्रकार हैं; http://code.google.com/p/autofac/wiki/RelationshipTypes देखें।

"कंटेनर साझा करना" निराश है क्योंकि यह कक्षा की निर्भरताओं को छिपाने के लिए प्रेरित करता है। यदि कंटेनर पर निर्भरता लिया जाता है, या वैश्विक "आईओसी" ऑब्जेक्ट के रूप में संदर्भित किया जाता है, तो विशिष्ट निर्भरताओं की अभिव्यक्ति खो जाती है।

पदानुक्रम के नीचे निर्भरता को हल करना कोई समस्या नहीं होनी चाहिए, क्योंकि आप पहले ही c'tor इंजेक्शन का उपयोग कर रहे हैं, मुझे यकीन नहीं है कि आपकी समस्या क्या है। सहायक आधार हैं, जैसे कि आपकी बेस क्लास निर्भरता बदलती है, तो अपने सभी उप-वर्गों को संशोधित करना। सौभाग्य से, ऑटोफैक के पास कुल सेवाओं (http://code.google.com/p/autofac/wiki/AggregateService) में इसका उत्तर है।

ऑटोफैक एक महान, गहरा टूल है। एक और सुझाव, यदि आप अभी शुरू कर रहे हैं तो कृपया अपने सिर को ऑब्जेक्ट लाइफटाइम और आजीवन स्कॉप्स (विशेष रूप से http://nblumhardt.com/2011/01/an-autofac-lifetime-primer/) के चारों ओर लपेटने के लिए कुछ समय दें। सौभाग्य!

0

Autofac के लिए .NET कोर

स्थापित

PM> Install-Package Autofac.Core.NonPublicProperty 

उपयोग

builder.RegisterType<AppService>() 
    .AsImplementedInterfaces() 
    .AutoWireNonPublicProperties(); 
संबंधित मुद्दे