5

मैं अपने नियंत्रकों में सेवा इंजेक्शन के लिए Autofac उपयोग करने के लिए मेरी Asp.Net MVC3 परियोजना बदलने की प्रक्रिया में हूँ। अब तक यह बहुत सरल है। मेरी सेवाओं में सभी में टेलीरिक ओपनएप डीबी संपत्ति है जिसे मैं रचनाकारों (सेवा बेस क्लास में) के माध्यम से इंजेक्ट करता हूं। और मेरे नियंत्रकों में सभी सेवाओं के लिए कन्स्ट्रक्टर गुण होते हैं जो इंजेक्शन भी प्राप्त करते हैं।Autofac संपत्ति इंजेक्शन

public class AuditInfo 
{  
    public string RemoteAddress { get; set; } 

    public string XForwardedFor { get; set; } 

    public Guid UserId { get; set; } 

    public string UserName { get; set; } 
} 

मेरी सेवा की कक्षाओं में मेरे OpenAccess db संपत्ति आदेश के रूप में उपयोग करने के लिए इस वर्ग यह करने में इंजेक्शन का एक उदाहरण की जरूरत है:

मैं एक वर्ग AuditInfo कहा जाता है जो एक नियंत्रक की लेखापरीक्षा योग्य गुण समाहित है विभिन्न डेटाबेस कॉल में ऑडिटिंग जानकारी।

समस्या यह है कि यह एक वर्ग नहीं है जिसे एप्लिकेशन_स्टार्ट पर तत्काल दोहराया जा सकता है क्योंकि इसके कम से कम दो गुण, RemoteAddress और XForwardedFO OnActionExecuting के शुरुआती चरण में आबादी वाले हैं, यानी अनुरोध चर मौजूद हैं।

इसलिए, मैं यह मेरी BaseController वर्ग के OnActionExecuting विधि में इस तरह के रूप का दृष्टांत:

protected override void OnActionExecuting(ActionExecutingContext filterContext) 
{ 
    base.OnActionExecuting(filterContext); 
    db.AuditInfo = AuditInfo;          
} 

public AuditInfo AuditInfo 
{ 
    get 
    { 
     return new AuditInfo() 
     { 
      RemoteAddress = this.Request.ServerVariables["REMOTE_ADDR"], 
      XForwardedFor = this.Request.ServerVariables["X_FORWARDED_FOR"], 
      UserId = this.UserId, 
      UserName = this.UserName 
     }; 
    } 
} 

तो - मेरी समस्या/प्रश्न हैं:

  1. मैं में इस प्रत्यक्ष पहुंच पसंद नहीं है OnActionExecuting में OpenAccess डीबी प्रॉपर्टी में।
  2. मैं इस AuditInfo मूल रूप से किसी AuditInfo संपत्ति में इंजेक्ट किया जा करना चाहते हैं कहीं भी
  3. मुझे नहीं लगता क्योंकि सेवा डाटाबेस पर निर्भर मैं AuditInfo के लिए निर्माता इंजेक्शन का उपयोग कर सकते हैं - नियंत्रकों सेवाओं पर निर्भर - db AuditInfo पर निर्भर करता है, लेकिन AuditInfo तब तक उपलब्ध नहीं है जब तक कि नियंत्रक को तत्काल नहीं किया जाता है और उसका पहला अनुरोध प्राप्त होता है। => सर्कुलर निर्भरता ...

मैं कैसे सेटअप autofac AuditInfo एक संपत्ति के रूप में यह है कि किसी भी वर्ग के लिए सुई हैं? या सर्कुलर निर्भरता को कम करने और लैम्ब्डा/आलसी कन्स्ट्रक्टर गुणों के कुछ रूपों का उपयोग करने का एक बेहतर तरीका है?

क्या यह सब कुछ इस बात से संबंधित है कि लेखापरीक्षा को हर अनुरोध पर संभावित रूप से अनावश्यक रूप से प्रारंभ किया जाता है, भले ही बहुत से अनुरोध एक ही सत्र का हिस्सा हो और अलग-अलग आईपी पता/उपयोगकर्ता जानकारी न हो?

धन्यवाद

+0

मैं इस समस्या/प्रश्न 3 से असहमत - के रूप में स्टीवन बताते हैं आप 'उपयोग कर सकते हैं HttpContext.Current'। इसलिए 'ऑडिट इंफो' नियंत्रक पर निर्भर नहीं है, इसलिए कोई परिपत्र निर्भरता नहीं है, इसलिए यदि आप चाहें तो 'ऑडिट इंफो' को कन्स्ट्रक्टर-इंजेक्ट कर सकते हैं। –

+0

खैर - मुझे लगता है कि ऐसा इसलिए है क्योंकि प्रस्तावित समाधान नियंत्रक के अंदर AuditInfo ऑब्जेक्ट को प्रारंभ करने के बजाय अनुरोध ऑब्जेक्ट का संदर्भ देने के लिए वैश्विक स्थैतिक चर का उपयोग कर रहा है जहां अनुरोध ऑब्जेक्ट स्वाभाविक रूप से मौजूद है। मुझे लगता है कि सर्वर चर अभी भी अनुप्रयोग_स्टार्ट में मौजूद नहीं है, जहां इंजेक्शन हो रहा है, क्योंकि एक क्रिया को पहले बुलाया जाना चाहिए, नहीं? – t316

उत्तर

2

यह Autofac's MVC Integration can resolve an HttpRequestBase for you पता चला है। तो आपको सीधे HttpContext.Current.Request संदर्भित करने की आवश्यकता नहीं है।

पर्दे के पीछे

Autofac के कार्यान्वयन uses HttpContext.Current। यह काम करता है क्योंकि MVC ढांचे सेट HttpContext.Current अपने कोड (या Autofac के) चलाता है पहले।तो कोई परिपत्र निर्भरता नहीं है - HttpContext.Current.Request पर अनुरोध "स्वाभाविक रूप से मौजूद है" जितना आपके नियंत्रक में उतना ही है। (This question तरह का बताते हैं कि कैसे)

तो तुम एक IAuditInfoFactory कर सकता है स्टीवन पता चलता है, लेकिन मांग इसके निर्माता में एक HttpRequestBase बजाय HttpContext.Current का उपयोग कर यदि यह आपके स्थैतिक चर संदर्भित नहीं बारे में बेहतर महसूस करता है के रूप में।

इसके अलावा, वहाँ कोई एक सर्कुलर निर्भरता है और तुम सकता है AuditInfo निर्माता-इंजेक्षन अगर आप चाहते हैं:

builder.Register(c => c.Resolve<IAuditInfoFactory>().CreateNew()) 
    .As<AuditInfo>() 
    .InstancePerHttpRequest(); 
+0

स्टीवन ने सही उत्तर की नींव तैयार करने का एक अच्छा काम किया है, हालांकि एचटीपीआरक्वैस्टबेस इंजेक्शन की कमी और डिफ़ॉल्ट बिंदु। क्रैमर के उस बिंदु के अतिरिक्त उसका जवाब थोड़ा और पूरा हो जाता है। निश्चित नहीं - मुझे इस तरह की स्थिति में सही उत्तर के न्यायसंगत अंकन को संभालने के लिए कैसे लगाया गया है - कृपया मुझे बताने में संकोच न करें। अभी के लिए मैं डिफ़ॉल्ट रूप से चिह्नित कर रहा हूँ। क्रैमर का जवाब सही के रूप में। धन्यवाद – t316

2

जवाब है: एक कारखाने का उपयोग करें।

प्रकार इसकी आवश्यकता है कि में एक IAuditInfoFactory सम्मिलित करें, और इस तरह एक कार्यान्वयन बनाने के लिए:

public class HttpRequestAuditInfoFactory : IAuditInfoFactory 
{ 
    // Service for requesting information about the current user. 
    private readonly ICurrentUserServices user; 

    public HttpRequestAuditInfoFactory(ICurrentUserServices user) 
    { 
     this.user = user; 
    } 

    AuditInfo IAuditInfoFactory.CreateNew() 
    { 
     var req = HttpContext.Current.Request; 

     return new AuditInfo() 
     { 
      RemoteAddress = req.ServerVariables["REMOTE_ADDR"], 
      XForwardedFor = req.ServerVariables["X_FORWARDED_FOR"], 
      UserId = this.user.UserId, 
      UserName = this.user.UserName 
     }; 
    } 
} 

आप उस वर्ग रजिस्टर कर सकते हैं इस प्रकार है:

builder.RegisterType<HttpRequestAuditInfoFactory>() 
    .As<IAuditInfoFactory>() 
    .SingleInstance(); 

अब आप इंजेक्षन कर सकते हैं

+0

त्वरित प्रतिक्रिया के लिए धन्यवाद। यह काम करना चाहिए, लेकिन क्या यह समाधान वास्तव में HttpContext.Current.Rurrent.Request को संदर्भित करने पर निर्भर करता है और HttpContext.Current.Request के प्राकृतिक जीवन चक्र के दौरान आवश्यक चर संग्रहीत करने के बजाय विदेशी संदर्भ में इसे चर पढ़ने और उन चरों को इंजेक्शन देने के लिए ढीले युग्मन के साथ विदेशी संदर्भ? मतलब - IAuditInfoFactory कार्यान्वयन को System.Web को संदर्भित करने की आवश्यकता है और इसके लिए सीधे HttpContext.Current.Request के बारे में पता है ... – t316

+0

यह विशेष 'HttpRequestAuditInfoFactory' कार्यान्वयन वास्तव में' HttpContext' पर एक कठिन निर्भरता लेता है। उस अर्थ में यह मंच जागरूक है। यह कोई समस्या नहीं है, लेकिन इसी कारण से यह आपके आवेदन का हिस्सा नहीं है (या नहीं होना चाहिए), लेकिन जिसे हम [रचना रूट] कहते हैं उसका हिस्सा होना चाहिए (http://blog.ploeh.dk/2011/ 07/28/CompositionRoot.aspx) (सीआर)। यह एप्लिकेशन का स्टार्ट-अप पथ है। सीआर की तुलना में कोई अन्य हिस्सा इस 'HttpRequestAuditInfoFactory' के अस्तित्व से अवगत होना चाहिए। एप्लिकेशन केवल 'IAuditInfoFactory' के बारे में जानता है। – Steven

+0

क्योंकि शेष एप्लिकेशन 'IAuditInfoFactory' के बारे में जानता है, लेकिन' HttpRequestAuditInfoFactory' के बारे में नहीं, यह आपके अनुप्रयोग को माइग्रेट करना आसान बनाता है - उदाहरण के लिए- एक विंडोज सेवा। आपको विंडोज सेवा के सीआर ('मुख्य' विधि) में 'IAuditInfoFactory' के विंडोज सेवा विशिष्ट कार्यान्वयन की आवश्यकता होगी और 'HttpRequestAuditInfoFactory'' की बजाय इसे तार करें। – Steven