6

मैं सिंगल-विधि इंटरफेस के बजाय नामित प्रतिनिधियों का उपयोग कर प्रयोग कर रहा हूं। यह, कोड आकार के लिए कुछ फायदे हैं के रूप में हम से (हटाया मामले को बढ़ा-चढ़ा के लिए नहीं इतनी के रूप में कुछ लाइनब्रेक) जा सकते हैं:कैसल विंडसर के साथ स्थैतिक बंद करने के लिए कोई आसान तरीका है?

public interface IProductSource 
{ 
    IEnumerable<Product> GetProducts(); 
} 
public class DataContextProductSource : IProductSource 
{ 
    private readonly DataContext _DataContext; 
    public DataContextProductSource(DataContext dataContext) 
    { 
     if (dataContext == null) throw new ArgumentNullException("dataContext"); 
     _DataContext = dataContext; 
    } 
    public IEnumerable<Product> GetProducts() 
    { 
     return _DataContext.Products.AsEnumerable(); 
    } 
} 

रहे हैं:

public delegate IEnumerable<Product> DGetProducts(); 
public static class DataContextFunctions 
{ 
    public DGetProducts GetProducts(DataContext dataContext) 
    { 
     if (dataContext == null) throw new ArgumentNullException("dataContext"); 
     return() => dataContext.Products.AsEnumerable(); 
    } 
} 

यह मूलतः तथ्य का लाभ ले जा रहा है कि एक बार जब आप निर्भरता इंजेक्शन के साथ काफी दूर जाते हैं, तो बहुत से वर्ग बंद होने से थोड़ा अधिक हो जाते हैं। उन वर्गों को लम्बास लौटने वाले कार्यों के साथ प्रतिस्थापित किया जा सकता है। संबंधित कार्यों के पूरे सेट (जिन्हें किसी भी परिवर्तनीय स्थिति को समाहित करने की आवश्यकता नहीं है, लेकिन "मानक" निर्भरता इंजेक्शन में कक्षाओं का उपयोग करके व्यक्त किया गया होगा), फिर उसे एक स्थिर वर्ग (या "मॉड्यूल" VB parlance में) में घुमाया जा सकता है। ।

यह सब ठीक है और अच्छा है, लेकिन मुझे कैसल विंडसर के साथ इन स्थिर तरीकों को पंजीकृत करने का सबसे अच्छा तरीका खोजने में परेशानी हो रही है। कोई निर्भरता के साथ तरीके आसान कर रहे हैं:

Component.For<DGetIntegers>().Instance(Integers.GetOneToTen) 

लेकिन ऊपर से हमारे DataContextFunctions.GetProducts कुछ निर्भरता है। सबसे अच्छा तरीका है मैं इस रजिस्टर करने के लिए मिल गया है है:

Component.For<DGetProducts>().UsingFactoryMethod(
    kernel => DataContextFunctions.GetProducts(kernel.Resolve<DataContext>()) 

यह काफी वर्बोज़ प्राप्त कर सकते हैं, और स्पष्ट रूप से प्रत्येक निर्भरता के लिए सीधे गिरी पूछने के लिए होने तरह की बात एक सा हरा दिया। मुझे ऐसा लगता है कि एक कंटेनर की सभी स्थिर जानकारी की आवश्यकता होनी चाहिए, इसलिए ऐसा करना संभव होना चाहिए।

सवाल यह है कि कैसल विंडसर (या किसी अन्य कंटेनर) के पास ऐसा करने का एक आसान तरीका है जिसे मैंने याद किया है, या क्या तकनीकी समस्याएं उत्पन्न हुई हैं, या क्या यह बहुत ही उपयोगी मामला है शामिल?

उत्तर

4

एक दिलचस्प तरीका है कि। मुझे लगता है कि आप इसे एक कस्टम एक्टिवेटर के साथ आसानी से काम कर सकते हैं।

+0

धन्यवाद, Krzysztof। मैं इसे कभी-कभी कोशिश करूंगा और परिणामों पर वापस रिपोर्ट करूंगा। शुरू करने के लिए एक अच्छी जगह के लिए कोई लिंक? – ninjeff

+0

@ninjeff अगर आप 2.5.x पर हैं तो दस्तावेज आपको दस्तावेज़ों को शुरू करना चाहिए .castleproject.org/(S(hucszcu5ilznbv45fvrim355))/... यदि आप 3.0 बीटा पर हैं, तो कुछ एपीआई परिवर्तन हुए हैं हालांकि अवधारणाएं अभी भी हैं वही। मुझे बताएं कि क्या डॉको –

+0

से कम है, तो मैं यह काम करने में सक्षम था। मैं एक घंटे में अपने उत्तर के साथ एक लिंक और विवरण पोस्ट करूंगा (मेरे जैसे कम-कर्मा उपयोगकर्ता आठ घंटे के भीतर अपने प्रश्नों का उत्तर नहीं दे सकते हैं)। – ninjeff

10

लघु जवाब

आप एक डि कंटेनर (कैसल विंडसर) प्रदर्शन समारोह रचना बनाने के लिए कोशिश कर रहे हैं, लेकिन यह वास्तव वस्तु रचना पर लक्षित है। यह आपको बहुत घर्षण देने जा रहा है। मेरा अनुमान है कि आपको अन्य कंटेनरों के साथ एक ही अनुभव मिल जाएगा।

डी कंटेनर ऑब्जेक्ट उन्मुख अवधारणाओं के आसपास डिजाइन किए गए हैं - विशेष रूप से सोल्ड। वे इन सिद्धांतों के साथ बहुत अच्छी तरह से काम करते हैं क्योंकि उन्हें कन्स्ट्रक्टर इंजेक्शन और ऑटो-वायरिंग जैसी चीजों की अंतर्निहित समझ के साथ डिजाइन किया गया था।

अधिक कार्यात्मक दृष्टिकोण के साथ कुछ भी गलत नहीं है, लेकिन मुझे ऑब्जेक्ट संरचना के बजाय फ़ंक्शन संरचना के चारों ओर एक डी कंटेनर बनाया गया है।

लांग जवाब

डि के लिए एक सामान्य सिद्धांत के रूप में प्रतिनिधियों के उपयोग के कारणों की एक जोड़ी के लिए स्थिर टाइप किया भाषाओं में समस्याग्रस्त किया जा करने के लिए (कम से कम .NET में दिया जाता है)। संकल्पनात्मक रूप से delegate can be considered as an anonymous Role Interface के बाद इस दृष्टिकोण के साथ कुछ भी गलत नहीं है। हालांकि, यह अस्पष्टता के कारण अनावश्यक हो जाता है।

सामान्य रूप से मैं देखता हूं कि सबसे सामान्य दृष्टिकोण बीसीएल के अंतर्निहित प्रतिनिधियों जैसे Func<T>, Action<T> और इसी तरह का उपयोग करना है।हालांकि, आपके पास Func<string> पर भरोसा करने वाले कई अलग-अलग उपभोक्ता हो सकते हैं, इस मामले में चीजें अस्पष्ट हो जाती हैं - सिर्फ इसलिए कि उपभोक्ता को Func<string> की आवश्यकता होती है इसका मतलब यह नहीं है कि उन्हें एक ही भूमिका में प्रतिनिधि की आवश्यकता होती है। यद्यपि यह यांत्रिक रूप से संभवतः DI के प्रतिनिधियों के साथ उपयोग करने के लिए है, तो क्या होता है कि प्रतिनिधि आवेदन भूमिका छिपाते हैं। भूमिकाएं गायब हो जाती हैं, केवल मैकेनिक्स छोड़ती हैं।

public delegate IEnumerable<Product> DGetProducts(); 

हालांकि, अगर आपको लगता है कि मार्ग अपनाते हैं, तो कुछ भी नहीं प्राप्त की है:

फिर आप के रूप में ओपी में सुझाव दिया कस्टम प्रतिनिधियों हर पात्र के लिए, के रूप में इस प्रतिनिधि ने सुझाव दिया निर्धारित कर सकते हैं। प्रत्येक भूमिका के लिए एक 'भूमिका प्रतिनिधि' को अभी भी परिभाषित किया जाना चाहिए। इसी तरह की एक इंटरफेस को परिभाषित करने के लिए कंट्रास्ट कि और यह स्पष्ट किया जाना चाहिए कि केवल बचत कोण कोष्ठक की एक जोड़ी और एक स्पष्ट विधि परिभाषा है:

public interface IProductSource { IEnumerable<Product> GetProducts(); } 

भूमि के ऊपर का एक बहुत (अगर कोई है) नहीं है यही कारण है कि।

आप भी इस चर्चा पर एक नज़र लेने के लिए चाहते हो सकता है: http://thorstenlorenz.wordpress.com/2011/07/23/dependency-injection-is-dead-long-live-verbs/

+0

आपके उत्तर के लिए धन्यवाद, मार्क। मैं वास्तव में एक पूरी तरह से कार्यात्मक दृष्टिकोण पर जाने की कोशिश नहीं कर रहा हूं, लेकिन एक संकर दृष्टिकोण के साथ प्रयोग कर रहा हूं। विभिन्न अवधारणाओं के लिए कार्यों बनाम वस्तुओं का उपयोग करने के ऊपर और डाउनसाइड्स को महसूस करने की कोशिश कर रहा है, और यह देखकर कि वे कितनी अच्छी तरह से बातचीत करते हैं। – ninjeff

+0

इंटरफेस के ऊपरी हिस्से के संबंध में, यह इंटरफेस के बजाए कार्यान्वयन कक्षाओं की लंबाई में अधिक है। – ninjeff

1

क्रज़ीज़टॉफ के पॉइंटर्स के आधार पर, मैं इसे संभालने के लिए एक कस्टम एक्टिवेटर लिखने में सक्षम था। स्रोत github पर है। इस तरह

रजिस्टर स्थिर प्रतिनिधियों (प्रश्न में उदाहरण का पालन करना):

container.Register(Component. 
    For<DGetProducts>(). 
    ImplementedBy(typeof(DataContextFunctions)). 
    Named("GetProducts"). 
    Activator<StaticDelegateActivator>()); 

कोड काफी हद तक DefaultComponentActivator के पुनर्लेखन है। मुझे विंडसर स्रोत कोड से DependencyTrackingScope कॉपी-पेस्ट करने की भी आवश्यकता है, क्योंकि यह आंतरिक है।

टेस्ट प्रोजेक्ट में एकल "परीक्षण" में केवल एक ही उपयोग केस शामिल है। मुझे संदेह नहीं है कि यह प्रॉक्सी जैसे अधिक उन्नत परिदृश्यों के लिए काम करेगा।

मैंने क्रिज़िट्टोफ के जवाब को स्वीकार कर लिया है, क्योंकि उनके मार्गदर्शन ने समाधान का नेतृत्व किया था।

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