2012-01-06 18 views
6

मैंने कक्षा पुस्तकालय के साथ एक दिलचस्प डिजाइन समस्या में भाग लिया है जिसे मैं लिख रहा हूं। मैं AuthorizeAttribute के एक कस्टम कार्यान्वयन कि मैं ग्राहकों को इस तरह का उपयोग करने में सक्षम होना चाहते हैं:कक्षा पुस्तकालय में AuthorizeAttribute में निर्भरता इंजेक्शन

[Protected("permission_name")] 

उपरोक्त कोड में, PermissionAttribute AuthorizeAttribute से विरासत और एक स्थानीय डिफ़ॉल्ट का उपयोग करता है (DefaultContext HttpContext उपयोग कर बनाई गई)।

दृश्यों के पीछे, विशेषता उपयोगकर्ताओं के लिए भूमिकाओं और अनुमतियों की जांच करने के लिए सुरक्षा सेवा का उपयोग करती है (सुरक्षा सेवा स्वयं क्लाइंट द्वारा प्रदत्त दृढ़ता सेवा का उपयोग करती है जो वे अपने ऐप की संरचना रूट में वायर कर सकते हैं)।

इसलिए मेरे गुणों को सुरक्षा सेवा के संदर्भ में कार्य करने की आवश्यकता है। चूंकि विशेषता रचनाकारों में केवल संकलन-समय स्थिरांक हो सकते हैं, मैं कन्स्ट्रक्टर इंजेक्शन का उपयोग नहीं कर सकता।

मैं एक डि ढांचे का उपयोग करने के लिए अपने ग्राहकों के लिए मजबूर नहीं करना चाहते - वे , एक आईओसी लाइब्रेरी का उपयोग कर यदि चाहें तो बिना और तार उनकी संरचना जड़ में आवश्यक निर्भरता की खोज करने के लिए सक्षम होना चाहिए।

  • पुस्तकालय एक सिंगलटन SecurityService का उपयोग है:

    यहाँ मेरी विकल्प हैं।

  • उपयोग संपत्ति इंजेक्शन, जो काम करेगा लेकिन
    1. यह निर्भरता होगा वैकल्पिक लगते हैं, जो यह नहीं है और
    2. मैं नहीं जानता कि मैं कहाँ एक अधिकृत विशेषता पर एक MVC अनुप्रयोग में संपत्ति इंजेक्शन कर सकते हैं ।

ऊपर 2. करने के लिए सम्भावित समाधान की तरह आवेदन स्टार्टअप पर विशेषता पर एक स्थिर संपत्ति के रूप में SecurityService का एक उदाहरण स्थापित करने और इसे एक बार से अधिक सेट होने से रोकने के लिए एक गार्ड खंड का उपयोग करते हैं करने के लिए, है यह:

class ProtectedAttribute : ... 
{ 
    private static ISecurityService _SecurityService ; 
    public static ISecurityService SecurityService 
    { 
     get 
     { 
      return _SecurityService ; 
     } 
     set 
     { 
      if (_SecurityService != null) 
       throw new InvalidOperationException("You can only set the SecurityService once per lifetime of this app.") ; 
      _SecurityService = value ; 
     } 
    } 
} 

सुरक्षा सेवा एक अमूर्त सेवा मुखौटा हो सकती है ताकि इसे एक अलग कार्यान्वयन द्वारा विस्तारित/प्रतिस्थापित किया जा सके।

क्या इस समस्या को हल करने का कोई बेहतर तरीका है?

अद्यतन: कुछ कोड जोड़ने को दिखाने के लिए कि कैसे मैं यह करने के लिए जा रहा हूँ:

public class ProtectedAttribute : ... 
{ 
    private string _Permission ; 
    public string Permission { get { return _Permission ; } /*...*/ } 

    public ProtectedAttribute(string permission) { /*...*/ } 
} 

सेटअप एक प्राधिकरण फिल्टर और निर्भरता कॉन्फ़िगर करें:

विशेषता है कि अनुमति देता है नाम पर एक सार्वजनिक संपत्ति जोड़ें Ninject के माध्यम से (Ninject का उपयोग करके):

using Ninject.Web.Mvc.FilterBindingSyntax; 

public class MyModule : Ninject.Modules.NinjectModule 
{ 
    public override void Load() 
    { 
    // mySecurityService instance below can have a singleton lifetime - perfect! 
    this.BindFilter<MyAuthorizationFilter>(FilterScope.Action, 0) 
     .WhenActionMethodHas<ProtectedAttribute>() 
     .WithConstructorArgument("securityService", mySecurityService) 
     .WithConstructorArgumentFromActionAttribute<ProtectedAttribute>("permission", p => p.PermissionName) ; 
    } 
} 

ओह यह है ... सुंदर sniffle

+0

के अनुकूल नहीं होना चाहिए यह एएसपी.नेट एमवीसी 3 है? –

+0

@ डारिन: हां न्यूनतम एमवीसी 3 की आवश्यकता है स्वीकार्य है। टैग अपडेट किया गया। –

+1

संबंधित: http://stackoverflow.com/questions/7192543/injecting-dependencies-into-asp-net-mvc-3-action-filters-whats-wrong-with-this/7194467#7194467 'IFilterProvider के लिए –

उत्तर

7

एएसपी.नेट एमवीसी 3 के साथ आप नए IFilterProvider के लिए एक्शन फ़िल्टर के साथ कन्स्ट्रक्टर इंजेक्शन का उपयोग कर सकते हैं। इस तरह आपको अब एक्शन फ़िल्टर के साथ अपने कंट्रोलर कार्यों को सजाने की आवश्यकता नहीं है।आप उन्हें इस इंटरफेस के लिए धन्यवाद और मार्कर विशेषता का उपयोग कर सकते हैं।

और यदि आप इसे मैन्युअल रूप से कार्यान्वित करने के लिए परेशान नहीं करना चाहते हैं तो आप हमेशा निनजेक्ट जैसे मौजूदा डी फ्रेमवर्क का उपयोग कर सकते हैं जो एक्शन फ़िल्टर निर्भरताओं को परिभाषित करने के लिए fluent way प्रदान करता है।

+0

+1 'जो काफी साफ समाधान देता है। इसी तरह की समस्या [एएसपी.नेट एमवीसी IFilterProvider और चिंताओं को अलग करना] (http://stackoverflow.com/questions/10708565/asp-net-mvc-ifilterprovider-and-separation-of-concerns) (कैसल विंडसर)। –

0

मेरे अनुप्रयोगों एक आधार आवेदन वर्ग कि आईओसी कंटेनर को उजागर करता है से विरासत।

public interface IInjectableApplication 
    { 
     IUnityContainer Container { get; } 
    } 

तो मैं एक आधार विशेषता वर्ग है, जो, हालांकि यह सच इंजेक्शन नहीं है इस

public abstract IocAwareActionFilterAttribute : ActionFilterAttribute{ 
    protected T ResolveItem<T>(ResultExecutedContext context) 
     { 
      var app = context.HttpContext.ApplicationInstance as IInjectableApplication; 
      if (app == null) { throw new NullReferenceException("Application is not IInjectable."); } 

      T c = (T)app.Container.Resolve(typeof(T)); 

      if (c == null) { throw new NullReferenceException(string.Format("Could not find injected {0}.", typeof(T).FullName)); } 
      return c; 
     } 

} 

के बारे में पता है, क्योंकि गुण 'सामान्य रूप से' का निर्माण नहीं कर रहे हैं, यह एक समान व्यवहार प्रदान करता है। किसी भी कारण से यह अन्य आईओसी

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