2013-08-21 8 views
15
के साथ कारखाने की जगह दिखाया गया है मेरे अपने कारखानों का निर्माण करने के

मैं आदी हूँ (इस उदाहरण के लिए सरल है):AutoFac

public class ElementFactory 
{ 
    public IElement Create(IHtml dom) 
    { 
     switch (dom.ElementType) 
     { 
      case "table": 
       return new TableElement(dom); 
      case "div": 
       return new DivElement(dom); 
      case "span": 
       return new SpanElement(dom); 
     } 
     return new PassthroughElement(dom); 
    } 
} 

मैं अंत में मेरे वर्तमान में एक आईओसी कंटेनर (AutoFac) का उपयोग करने के लिए चारों ओर हो रही है प्रोजेक्ट, और मुझे आश्चर्य है कि ऑटोफैक के साथ एक ही चीज़ को प्राप्त करने का कुछ जादू तरीका है?

+1

ऑटोफ़ैक के साथ इस कारखाने को बदलने का क्या फायदा है? – Steven

+0

क्षमा करें, जैसा कि मैंने कीथ्स के उत्तर पर मेरी टिप्पणी में संकेत दिया था, मैं उम्मीद कर रहा था कि कुछ ऑटोफैक वूडू होगा जो मुझे स्विच से बचने दें। स्विच से बचने का क्या फायदा है? मुझे पता नहीं है ... मुझे लगता है कि उन्हें उनके साथ एक विचलन के साथ प्रेरित किया गया है :( –

+1

आईओसी कोई जादू की छड़ी नहीं है। आप नामांकित पंजीकरण का उपयोग कर सकते हैं, और आप स्विच को हटा सकते हैं, लेकिन अंत में हमेशा कुछ प्रकार का होगा स्विचिंग तर्क। मेरी सलाह: कारखाने के किले का उपयोग करें और ऑटोफैक में कारखाने को पंजीकृत करें। – Steven

उत्तर

23

संक्षिप्त उत्तर: हां।

लंबा उत्तर: सबसे पहले, साधारण मामलों में जहां कक्षा फू IFoo के कार्यान्वयन के रूप में पंजीकृत है, कन्स्ट्रक्टर पैरामीटर या प्रकार Func<IFoo> के गुण ऑटोफैक द्वारा स्वचालित रूप से हल किए जाएंगे, बिना अतिरिक्त तारों की आवश्यकता होगी। ऑटोफैक एक प्रतिनिधि को इंजेक्ट करेगा जो मूल रूप से container.Resolve<IFoo>() निष्पादित करता है।

आपके जैसे जटिल मामलों में, जहां सटीक विवेक वापस इनपुट पैरामीटर पर आधारित है, आप दो चीजों में से एक कर सकते हैं। सबसे पहले, आप एक कारखाने विधि रजिस्टर कर सकते हैं के रूप में अपनी वापसी मान एक पैरामिट्रीकृत संकल्प प्रदान करने के लिए:

builder.Register<IElement>((c, p) => { 
    var dom= p.Named<IHtml>("dom"); 
    switch (dom.ElementType) 
    { 
     case "table": 
      return new TableElement(dom); 
     case "div": 
      return new DivElement(dom); 
     case "span": 
      return new SpanElement(dom); 
    } 
    return new PassthroughElement(dom); 
    }); 

//usage 
container.Resolve<IElement>(new NamedParameter("dom", domInstance)) 

यह नहीं है टाइप सुरक्षित (domInstance संकलक जाँच यह एक IHtml है सुनिश्चित करने के लिए नहीं किया जाएगा), और न ही बहुत स्वच्छ। इसके बजाय, एक और समाधान वास्तव में रजिस्टर करने के लिए एक समारोह के रूप में कारखाना विधि है:

builder.Register<Func<IHtml, IElement>>(dom => 
{ 
    switch (dom.ElementType) 
    { 
     case "table": 
      return new TableElement(dom); 
     case "div": 
      return new DivElement(dom); 
     case "span": 
      return new SpanElement(dom); 
    } 
    return new PassthroughElement(dom); 
}); 


public class NeedsAnElementFactory //also registered in AutoFac 
{ 
    protected Func<IHtml,IElement> CreateElement {get; private set;} 

    //AutoFac will constructor-inject the Func you registered 
    //whenever this class is resolved. 
    public NeedsAnElementFactory(Func<IHtml,IElement> elementFactory) 
    { 
     CreateElement = elementFactory; 
    } 

    public void MethodUsingElementFactory() 
    { 
     IHtml domInstance = GetTheDOM(); 

     var element = CreateElement(domInstance); 

     //the next line won't compile; 
     //the factory method is strongly typed to IHtml 
     var element2 = CreateElement("foo"); 
    } 
} 

आप के बजाय Autofac मॉड्यूल में डालने की ElementFactory में कोड रखने के लिए चाहते हैं तो आपके कारखाने विधि स्थिर कर सकता है और रजिस्टर कि (यह आपके मामले में विशेष रूप से अच्छी तरह से काम करता है क्योंकि आपकी फैक्ट्री विधि को स्थिर रूप से स्थिर किया जाता है):

public class ElementFactory 
{ 
    public static IElement Create(IHtml dom) 
    { 
     switch (dom.ElementType) 
     { 
      case "table": 
       return new TableElement(dom); 
      case "div": 
       return new DivElement(dom); 
      case "span": 
       return new SpanElement(dom); 
     } 
     return new PassthroughElement(dom); 
    } 
} 

... 

builder.Register<Func<IHtml, IElement>>(ElementFactory.Create); 
+1

धन्यवाद, यह वास्तव में उपयोगी है! मैं उम्मीद कर रहा था कि ऑटोफैक मुझे बदसूरत स्विच स्टेटमेंट से बचने में मदद करेगा, लेकिन वहां पर, मुझे देखकर, व्यावहारिक रूप से मुझे अपने सभी तीन ब्लॉक ब्लॉक में मजाक कर रहा है :) –

+2

वैसे भी "कुंजी रजिस्ट्रेशन" का उपयोग करना संभव है, प्रत्येक तत्व प्रकार के नाम को संबंधित ऑब्जेक्ट प्रकार के लिए एक रिज़ॉल्यूशन विधि के लिए कुंजी के रूप में निर्दिष्ट करना। इस स्थिति में जटिलता यह है कि सभी संभावित रिटर्न प्रकार किसी कुंजी से जुड़े नहीं होते हैं (आपके पास एक डिफ़ॉल्ट केस है), और अन्य कारणों से तत्व नाम के IHtml माता-पिता की आवश्यकता होती है। तो, यह आपके कामकाजी कोड को लेने और इसे स्थापित करने के लिए सबसे आसान लग रहा था, इसलिए ऑटोफ़ैक इसका उपयोग कर सकता था। – KeithS

+2

पंजीकरण संकलित नहीं करता है: 'बिल्डर। रजिस्ट्रार > (ElementFactory.Create);' मुझे उम्मीद है कि यह इस तरह कुछ दिखने की उम्मीद करेगा: 'निर्माता। रजिस्ट्रार > ((संदर्भ, पैरामीटर) => (एचटीएमएल => ElementFactory.Create (एचटीएमएल)); ' –

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