26

के साथ निर्भरता इंजेक्शन का उपयोग कैसे करें I ASP.NET वेब फ़ॉर्म नियंत्रणों के साथ निर्भरता इंजेक्शन का उपयोग करने के लिए एक तरीका तैयार करने का प्रयास कर रहा हूं।एएसपी.नेट वेब फॉर्म

मैं नियंत्रण है कि खजाने सीधे बनाते हैं, और पहुँच सकते हैं और मैं एक पैटर्न रहा हूँ डेटा आदि

करने के लिए बाध्य करने के लिए जहाँ मैं नियंत्रण बाह्य (आईओसी) के खजाने पारित कर सकते हैं उन का उपयोग के बहुत सारे मिल गया है तो, मेरे नियंत्रण इस बात से अनजान रहते हैं कि कैसे भंडारों का निर्माण किया जाता है और वे कहां से आते हैं

मैं अपने नियंत्रण से आईओसी कंटेनर पर निर्भरता नहीं रखना चाहूंगा, इसलिए मैं केवल कन्स्ट्रक्टर के साथ नियंत्रण बनाने में सक्षम होना चाहता हूं या संपत्ति इंजेक्शन।

(और सिर्फ बातें, इन नियंत्रणों का निर्माण किया जा रहा है और रनटाइम पर एक सीएमएस द्वारा पृष्ठ पर रखा! जटिल)

किसी भी विचार? (Structuremap का उपयोग करता है)

public class PartialView : UserControl 
{ 
    protected override void OnInit(System.EventArgs e) 
    { 
     ObjectFactory.BuildUp(this); 
     base.OnInit(e); 
    } 
} 

कि कोई नियंत्रण है कि उस आधार वर्ग से विरासत इंजेक्षन जाएगा:

उत्तर

30

आप डिफ़ॉल्ट PageHandlerFactory को एक कस्टम के साथ बदलकर स्वचालित कन्स्ट्रक्टर इंजेक्शन का उपयोग कर सकते हैं। इस तरह आप निर्भरताओं को लोड करने के लिए एक ओवरलोडेड कन्स्ट्रक्टर का उपयोग कर सकते हैं। आपका पृष्ठ इस प्रकार दिखाई देंगे:

public partial class HomePage : System.Web.UI.Page 
{ 
    private readonly IDependency dependency; 

    public HomePage(IDependency dependency) 
    { 
     this.dependency = dependency; 
    } 

    // Do note this protected ctor. You need it for this to work. 
    protected HomePage() { } 
} 

का विन्यास कि कस्टम PageHandlerFactory web.config में किया जा सकता है इस प्रकार है:

<?xml version="1.0"?> 
<configuration> 
    <system.web> 
    <httpHandlers> 
     <add verb="*" path="*.aspx" 
     type="YourApp.CustomPageHandlerFactory, YourApp"/> 
    </httpHandlers> 
    </system.web> 
</configuration> 

आपका CustomPageHandlerFactory इस तरह दिख सकता:

public class CustomPageHandlerFactory : PageHandlerFactory 
{ 
    private static object GetInstance(Type type) 
    { 
     // TODO: Get instance using your favorite DI library. 
     // for instance using the Common Service Locator: 
     return Microsoft.Practices.ServiceLocation 
      .ServiceLocator.Current.GetInstance(type); 
    } 

    public override IHttpHandler GetHandler(HttpContext cxt, 
     string type, string vPath, string path) 
    { 
     var page = base.GetHandler(cxt, type, vPath, path); 

     if (page != null) 
     { 
      // Magic happens here ;-) 
      InjectDependencies(page); 
     } 

     return page; 
    } 

    private static void InjectDependencies(object page) 
    { 
     Type pageType = page.GetType().BaseType; 

     var ctor = GetInjectableCtor(pageType); 

     if (ctor != null) 
     { 
      object[] arguments = (
       from parameter in ctor.GetParameters() 
       select GetInstance(parameter.ParameterType) 
       .ToArray(); 

      ctor.Invoke(page, arguments); 
     } 
    } 

    private static ConstructorInfo GetInjectableCtor(
     Type type) 
    { 
     var overloadedPublicConstructors = (
      from constructor in type.GetConstructors() 
      where constructor.GetParameters().Length > 0 
      select constructor).ToArray(); 

     if (overloadedPublicConstructors.Length == 0) 
     { 
      return null; 
     } 

     if (overloadedPublicConstructors.Length == 1) 
     { 
      return overloadedPublicConstructors[0]; 
     } 

     throw new Exception(string.Format(
      "The type {0} has multiple public " + 
      "ctors and can't be initialized.", type)); 
    } 
} 

डाउनसाइड यह है कि यह पूर्ण ट्रस्ट में आपकी तरफ दौड़ते समय ही काम करता है। आप इसके बारे में अधिक जानकारी here पढ़ सकते हैं। लेकिन ध्यान दें कि आंशिक ट्रस्ट seems a lost cause में एएसपी.NET अनुप्रयोगों का विकास करना।

+0

हाय स्टीवन, मेरे पास इस परियोजना में कुछ ऐसा प्रोजेक्ट लागू है और यह वास्तव में अच्छा काम करता है। लेकिन अब मुझे एक समस्या का सामना करना पड़ रहा है। यहां वर्णित है "http://stackoverflow.com/questions/15692499/page-routing-in-asp-net-4-0-extensionless-url-versus-pagehandlerfactory-asp"। क्या आप कृपया एक नज़र डालें और शायद कुछ राय साझा कर सकते हैं? –

+0

कैसल विंडसर। कभी नहीं, मैंने इसे पृष्ठों में बूस्ट्रैपर से हल करके हल किया। यह अच्छा नहीं है, लेकिन हे, यह काम कर रहा है और अभी भी अच्छा लग रहा है। –

+0

मुझे यह उत्कृष्ट लेख http://www.codemag.com/Article/1210031 मिला है (मुझे लगता है कि एक और एसओ उत्तर से जुड़ा हुआ है, लेकिन अब मुझे कोई नहीं मिल रहा है) जिसमें उपर्युक्त समाधान से संबंधित अधिक उदाहरण कोड शामिल है, और दिलचस्प बात यह भी दिखाती है कि माइक्रोसॉफ्ट प्रबंधित एक्स्टेंसिबिलिटी फ्रेमवर्क (एमईएफ) आपको इस तरह की और समान निर्भरता इंजेक्शन समस्याओं को एक बहुत ही उपयोगी और थोड़ा गैर-मानक तरीके से हल करने में मदद कर सकता है। –

3

सबसे अच्छा तरीका है की तरह नियंत्रण के लिए एक आधार वर्ग है। का मेल है कि एक संपत्ति आधारित config के साथ, आप की तरह से नियंत्रित किए जाने में सक्षम हो जाएगा: सही नियंत्रण बनाने के बाद आप नियंत्रण के वारिस, शायद सीएमएस एक हुक है नहीं कर सकते हैं:

public partial class AdminHeader : PartialView 
{ 
    IMyRepository Repository{get;set;} 
} 

अद्यतन 1 , वहां आप बिल्डअप को कॉल कर सकते हैं। इसके अलावा यदि सीएमएस आपको उदाहरण लाने के लिए कुछ हुक करने की अनुमति देता है तो आप कन्स्ट्रक्टर आधारित इंजेक्शन का उपयोग कर सकते हैं, लेकिन मैं इस विशिष्ट परिदृश्य पर BuildUp को पसंद करता हूं क्योंकि asp.net के लिए इसके लिए कोई हुक नहीं है।

+0

प्रतिक्रिया के लिए धन्यवाद। मेरे पूर्णतावादी पक्ष नियंत्रणों को ऑब्जेक्ट फैक्ट्री फ्रेमवर्क यानी शुद्ध निर्भरता इंजेक्शन पर निर्भरता नहीं रखना चाहते हैं। जाहिर है यह नियंत्रण बनाने, बाहरी कुछ का तात्पर्य है। – Schneider

+0

पुन: अद्यतन 1. मुझे सीएमएस में चारों ओर एक पोक होगा और देखें कि मुझे कुछ भी मिल सकता है या नहीं। मुझे लगता है कि एएसपी.नेट में कन्स्ट्रक्टर आधारित इंजेक्शन के साथ एक समस्या यह है कि नियंत्रण उस बिंदु पर 'अवांछनीय' बन जाता है। जब तक डिजाइनर को पता न लगे कि उन्हें कैसे बनाया जाए। – Schneider

1

आप एप्लिकेशन_स्टार्ट global.asax ईवेंट में कुछ सिंगलटन उदाहरण भी बना सकते हैं और उन्हें सार्वजनिक स्थैतिक रीडोनली गुणों के रूप में उपलब्ध करा सकते हैं।

4

Autofac supports एएसपी.नेट वेबफॉर्म में काफी अप्रचलित निर्भरता इंजेक्शन। मेरी समझ यह है कि यह एक http मॉड्यूल का उपयोग कर एएसपी.नेट पेज लाइफसाइकिल में बस हुक करता है और संपत्ति इंजेक्शन करता है। एकमात्र पकड़ यह है कि नियंत्रण के लिए मुझे नहीं लगता कि इनिट इवेंट के बाद ऐसा होता है।

0

यह एक समाधान मैं हाल ही में पाइप लाइन में hooking से बचने के लिए प्रयोग किया जाता है (मुझे लगता है कि हर किसी को है कि भविष्य में मेरे कोड को देखती है confuses लगता है, लेकिन हाँ, मैं अपने फायदे के रूप में अच्छी तरह से देखें):

public static class TemplateControlExtensions 
{ 
    static readonly PerRequestObjectManager perRequestObjectManager = new PerRequestObjectManager(); 

    private static WIIIPDataContext GetDataContext(this TemplateControl templateControl) 
    { 
     var dataContext = (WIIIPDataContext) perRequestObjectManager.GetValue("DataContext"); 

     if (dataContext == null) 
     { 
      dataContext = new WIIIPDataContext(); 
      perRequestObjectManager.SetValue("DataContext", dataContext); 
     } 

     return dataContext; 
    } 

    public static IMailer GetMailer(this TemplateControl templateControl) 
    { 
     return (IMailer)IoC.Container.Resolve(typeof(IMailer)); 
    } 

    public static T Query<T>(this TemplateControl templateControl, Query<T> query) 
    { 
     query.DataContext = GetDataContext(templateControl); 
     return query.GetQuery(); 
    } 

    public static void ExecuteCommand(this TemplateControl templateControl, Command command) 
    { 
     command.DataContext = GetDataContext(templateControl); 
     command.Execute(); 
    } 

    private class PerRequestObjectManager 
    { 
     public object GetValue(string key) 
     { 
      if (HttpContext.Current != null && HttpContext.Current.Items.Contains(key)) 
       return HttpContext.Current.Items[key]; 
      else 
       return null; 
     } 

     public void SetValue(string key, object newValue) 
     { 
      if (HttpContext.Current != null) 
       HttpContext.Current.Items[key] = newValue; 
     } 
    } 
} 

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

Limit your abstractions: Refactoring toward reduced abstractions

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