12

मैं इस प्रकार एक कस्टम AuthorizeAttribute में एक dependancy इंजेक्षन करने की कोशिश कर रहा हूँ:विशेषताओं पर संपत्ति इंजेक्शन

public class UserCanAccessArea : AuthorizeAttribute 
{ 
    readonly IPermissionService permissionService; 

    public UserCanAccessArea() : 
     this(DependencyResolver.Current.GetService<IPermissionService>()) { } 

    public UserCanAccessArea(IPermissionService permissionService) 
    { 
     this.permissionService = permissionService; 
    } 

    protected override bool AuthorizeCore(HttpContextBase httpContext) 
    { 
     string AreaID = 
      httpContext.Request.RequestContext.RouteData.Values["AreaID"] as string; 

     bool isAuthorized = false; 

     if (base.AuthorizeCore(httpContext)) 
      isAuthorized = permissionService.UserCanAccessArea(AreaID, httpContext.User); 

     return isAuthorized; 
    } 
} 

यह काम करता है लेकिन जिसका अर्थ है मैं समस्याओं मेरी pervious question

में वर्णित प्राप्त एक सिंगलटन के रूप में हल करने जा रहा है

मैं जो करना चाहता हूं वह संपत्ति इंजेक्शन का उपयोग करना है, लेकिन चूंकि मेरी विशेषता स्वयं एकता द्वारा हल नहीं होती है, इसलिए मैं कंटेनर को किसी संपत्ति को अवरुद्ध करने और हल करने के लिए कॉन्फ़िगर करने का कोई तरीका नहीं ढूंढ पा रहा हूं।

public class UserCanAccessArea : AuthorizeAttribute 
{ 
    public IPermissionService permissionService { get; set; } 

    protected override bool AuthorizeCore(HttpContextBase httpContext) 
    { 
     string AreaID = 
      httpContext.Request.RequestContext.RouteData.Values["AreaID"] as string; 

     bool isAuthorized = false; 

     if (base.AuthorizeCore(httpContext)) 
      isAuthorized = permissionService.UserCanAccessArea(AreaID, httpContext.User); 

     return isAuthorized; 
    } 
} 

कंटेनर:: मैं निम्नलिखित की कोशिश की है

container.RegisterType<UserCanAccessArea>(new InjectionProperty("permissionService")); 

लेकिन संपत्ति कार्यावधि में हमेशा रिक्त है।

क्या किसी ने इसे हासिल किया है और यदि ऐसा है तो आपके पास एक उदाहरण है?

उत्तर

27

आपको निर्भरता इंजेक्शन को पूरी तरह से गुणों में रोकना चाहिए। इस आलेख में इसका कारण बताया गया है: Dependency Injection in Attributes: don’t do it!। संक्षेप में लेख बताता है कि:

  • कन्स्ट्रक्टर इंजेक्शन संभव नहीं है, क्योंकि एक विशेषता उदाहरण के निर्माण को अवरुद्ध नहीं किया जा सकता है; सीएलआर नियंत्रण में है।
  • संपत्ति इंजेक्शन का उपयोग नाजुक है, क्योंकि इसका परिणाम Temporal Coupling है, जिसे रोका जाना चाहिए।
  • गुणों में निर्भरता इंजेक्शन कंटेनर की कॉन्फ़िगरेशन की शुद्धता को सत्यापित करना असंभव बनाता है।
  • एमवीसी और वेब एपीआई कैश विशेषताओं जैसे फ्रेमवर्क, गलती से captive dependencies को बग बनाने के लिए बहुत आसान बनाते हैं।

आप यहाँ दो विकल्प हैं:

  1. , गुण निष्क्रिय बनाओ अपने व्यवहार (सेवा) द्वारा डेटा (विशेषता) विभाजित करके referenced article और this related article मार्क सीनैन से में समझाया गया है।
  2. this answer में बताए गए अनुसार अपनी विशेषताओं को humble objects में बदलें। इसका मतलब है कि:
    1. सभी निर्भरताओं में एक कस्टम सेवा में विशेषता से सभी तर्क निकालें।
    2. उस सेवा को अपने कंटेनर में पंजीकृत करें।
    3. विशेषता के तरीके (AuthorizeCore अपने मामले में) सेवा लोकेटर/निर्भरता रीसोलवर से सेवा को हल करने और सेवा की विधि को कॉल करने से कुछ भी नहीं करें। यहां ध्यान देने योग्य महत्वपूर्ण है कि आप कन्स्ट्रक्टर इंजेक्शन, प्रॉपर्टी इंजेक्शन नहीं कर सकते हैं और सेवा को निजी स्थिति में संग्रहीत नहीं किया जा सकता है (जैसा कि आपने पहले ही देखा है)।

कौन सा विकल्प का उपयोग करने के लिए:

  • विकल्प 1 का प्रयोग करें आप अपने डिजाइन साफ ​​रखने में बहुत उत्सुक हैं, या आप कुछ विशेषताओं है कि आप इस तरह से लागू करने की आवश्यकता की तुलना में अधिक है, या आप लागू करना चाहते हैं विशेषताओं को एक असेंबली में परिभाषित किया गया है जो System.Web.Mvc पर निर्भर नहीं है।
  • अन्यथा विकल्प 2 का उपयोग करें।
+0

मैं विकल्प 1 की खोज कर रहा हूं, और ऐसा लगता है कि यदि आप dbcontext को इनरक्वैस्टस्कोप (निनजेक्ट) को हल करने के लिए निर्दिष्ट किया गया है तो इसका उपयोग नहीं किया जा सकता है। अन्यथा पूरी तरह से काम करता है। मैंने पहली बार सेवा लोकेटर (विरोधी पैटर्न, लेकिन सेवा वस्तुओं के निर्माण को हल करने के साथ) की कोशिश की है। कस्टम अधिकृत विशेषता के साथ समस्या यह है कि इसे रनटाइम पर बनाया गया है और InRequestScope का पालन नहीं करता है। अगर मैं गलत हूं कृपया मुझे सही। –

+0

मैं InRequestScope विकल्प का उपयोग करना चाहता हूं, क्योंकि अलग-अलग रिपॉजिटरीज़ के साथ काम करते समय एक और एक ही dbcontext होना चाहता है, और यूनिटऑफवर्क का उपयोग करने में सक्षम होना - dbcontext में savechanges को कॉल करने के लिए एक स्थान। –

+0

एक विचार सेवा के लिए DI का उपयोग नहीं करना है, लेकिन केवल प्राधिकरण फ़िल्टर में उपयोग की जाने वाली वास्तविक वस्तु बनाएं। क्या यह एक अच्छा दृष्टिकोण है? यह मेरा कोड बदसूरत सेवा के रूप में करेगा जो मुझे अन्य निर्भर सेवाओं और भंडारों के लिए चाहिए .... –

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